wordCloud = (data,word,frequency,maxSize,type) => {
if (type===undefined) {
data.map(d => d.type = 0)
}
const height = 1150;
const margin = {
t: 0,
l: 120,
r: 120,
b: 0,
}
const padding = 2;
let ext = d3.extent(data, d => d[type])
let xScale = d3.scaleLinear()
.domain(ext)
.range([margin.l, width - margin.l - margin.r]);
let svg = d3.select(html`<svg></svg>`)
.attr('width', width)
.attr('height', height);
const colors = d3.schemeSet1
.slice(0, new Set(data.map(d=> d[type])).size)
const luminance = 50;
const textColor = d3.scaleQuantile().range(["#fff", "#000"]).domain([0, luminance, 100]);
const r = d3.scaleSqrt()
.domain([0, d3.max(data, d => d[frequency])])
.range([0, maxSize]);
// define the simualtion engine
var simulation = d3.forceSimulation(data)
.force("x", d3.forceX(width/2).strength(0.008))
.force("y", d3.forceY(height/2).strength(0.08))
.force("collide", d3.forceCollide().radius(d=> r(d[frequency]) + padding).iterations(5))
.force('center', d3.forceCenter(width/2, 1.6*height/2))
.alpha(0.7);
///////////////////
function randomize() {
simulation
.force("x", d3.forceX(width/2).strength(0.1))
.force("y", d3.forceY(width/2).strength(0.1))
.force("collide", d3.forceCollide().radius(d=> r(d[frequency]) + padding).iterations(1))
//.force('center', d3.forceCenter(width/2, 1.6*height/2))
.alpha(0.1)
.on('end', () => {
simulation
.alpha(0.1)
.force("x", d3.forceX(width/2).strength(0.008))
.force("y", d3.forceY(width/2).strength(0.1))
.on('end', null)
// .force("charge", d3.forceManyBody().strength(-1))
.restart();
}).restart();
}
function split() {
simulation
.force("x", d3.forceX(d=> xScale(d[type])).strength(0.5))
.force("y", d3.forceY(height/2).strength(0.5))
.force("collide", d3.forceCollide().radius(d=> r(d[frequency]) + padding).iterations(5))
.alpha(0.5)
.restart();
}
/////////////
// create a layer or group
let gBubble = svg
.selectAll('gBubble')
.data(data);
gBubble.exit().remove();
let bubble = gBubble.enter()
.append('g')
.classed('gBubble', true)
.attr('id',d => d[word]);
bubble
.append('circle')
.attr('r', d => r(d[frequency]))
.attr('fill', d => colors[+d[type]])
.attr('fill-opacity', 0.4)
.attr('stroke', d => colors[+d[type]])
.attr('stroke-width', 1)
.style("cursor", "pointer");
let text= bubble
.append('text');
const textLabels = text
.text( d => (d[word]))
.style('text-anchor','middle')
.attr("dominant-baseline", "central")
.attr('font-family', 'sans-serif')
.attr('font-size', d => r(d[frequency])/2+'px' )
.attr('font-weight','normal')
.attr('fill', d => textColor(d3.hcl(colors[+d[type]]).l))
.style("cursor", "pointer")
// const tooltip = bubble
// .append('g')
// .style('visibility', 'hidden');
// const tipRect = tooltip
// .append('rect')
// .classed('tooltip', true)
// const tip = tooltip
// .append('text')
// .style('x', 0)
// .style('y', 10)
// .text(d => d[type] + ', ' + d[frequency]);
// bubble
// .on('mouseover', function(e,idx) {
// let node = d3.select(bubble.nodes()[idx])
// node
// .select('.tooltip')
// .style('visibility', 'visible');
// })
// .on('mouseout', function(e,idx) {
// let node = d3.select(bubble.nodes()[idx])
// node
// .select('.tooltip')
// .style('visibility', 'hidden');
// });
gBubble = gBubble
.merge(bubble);
gBubble.call(drag(simulation));
simulation.nodes(data)
.on('tick', () => {
gBubble
.attr('transform', d => 'translate('+ (d.x) +','+ (d.y)+')');
})
return Object.assign(svg.node(), { randomize, split });
}