Published
Edited
Jul 6, 2021
Insert cell
Insert cell
Insert cell
Insert cell
ppDataFile = FileAttachment("data_prova@2.json")
Insert cell
ppData = await ppDataFile.json()
Insert cell
md`# Bubblechart`
Insert cell
Insert cell
bubbleChart = wordCloud(bubbleData, 'color', 'freq', 40, 'timeFrame')
// declare type column only if you have a label you want to use to color bubbles
Insert cell
Insert cell
Insert cell
wordCloud = (data, word, frequency, maxSize, xAxis) => {
if (xAxis === undefined) {
data.map(d => (d.xAxis = 0));
}
const height = 400;
const margin = {
t: 0,
l: 50,
r: 20,
b: 0
};
const padding = 2;

const time = d3.set(bubbleData.map(d => d['timeFrame'])).values();

let x = d3
.scalePoint()
.domain(time)
.range([margin.l, width - margin.l - margin.r]);

// create the SVG container
let svg = d3
.select(html`<svg></svg>`)
.attr('width', width)
.attr('height', height);

const xaxis = svg
.append("g")
.attr("transform", `translate(0,${height - 50})`)
.call(d3.axisBottom(x))
.attr('font-family', 'Roboto Mono')
.attr('font-size', '12px')
.attr('font-weight', 'normal')

// Scala di colore categorica (scegliete quella che si adatta meglio al vostro progetto)
const colorScale = d3.scaleOrdinal(d3.schemeAccent);

// color text black or white according to the luminance value of the node
const luminance = 50;
const textColor = d3
.scaleQuantile()
.range(["#fff", "#000"])
.domain([0, luminance, 100]);

// define scale for radius
const r = d3
.scaleSqrt()
.domain([0, d3.max(data, d => d[frequency])])
.range([0, maxSize]);

// define the simualtion engine
const simulation = d3
.forceSimulation(data)
.force("x", d3.forceX(d => x(d[xAxis])).strength(1))
.force("y", d3.forceY(height / 2).strength(0.2))
.force(
"collide",
d3
.forceCollide()
.radius(d => r(d[frequency]) + padding)
.iterations(10)
)
.alpha(0.2);

// 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 => colorScale(d[word]))
.attr('fill-opacity', 0.8)
//.attr('stroke', d => d3.rgb(colorScale(d[word])).darker(1))
//.attr('stroke-width', 1);

const textLabels = bubble
.append('text')
.text(d => d[word])
.style('text-anchor', 'middle')
.attr("dominant-baseline", "central")
.attr('font-family', 'Roboto Mono')
.attr('font-size', '12px')
.attr('font-weight', 'normal')
.style('stroke', 'white')
.style('stroke-width', 1);

const textBck = bubble
.append('text')
.text(d => d[word])
.style('text-anchor', 'middle')
.attr("dominant-baseline", "central")
.attr('font-family', 'Roboto Mono')
.attr('font-size', '12px')
.attr('font-weight', 'normal');
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());
}
Insert cell
drag = simulation => {
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}

function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}

function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}

return d3
.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);
}
Insert cell
Insert cell
d3 = require("d3@5", "d3-sankey@0.12")
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more