chart3 = {
const height = width;
const singleColor = "gray";
const boundaryColor = "red"
const context = DOM.context2d(width, height);
const nodes = data.map(Object.create);
const forceDistance = -20;
const maxBoundaryDistance = 0;
const simulation = d3.forceSimulation(nodes)
.alphaTarget(0.3)
.velocityDecay(0.1)
.force("x", d3.forceX().strength(0.01))
.force("y", d3.forceY().strength(0.01))
.force("collide", d3.forceCollide().radius(d => d.r + 1).iterations(3))
.force("charge", d3.forceManyBody().strength((d, i) => i ? 0 : -width * 2 / 50))
.on("tick", ticked);
console.log(nodes)
d3.select(context.canvas)
.on("touchmove", event => event.preventDefault())
.on("pointermove", pointermoved);
invalidation.then(() => simulation.stop());
const fadeDuration = 3000;
const fadeOutRate = 0.003;
const fadingNodes = [];
function getRandomColor() {
const letters = "0123456789ABCDEF";
let color = "#";
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
function getRandomColorFromArray() {
const colors = ["#FF5733", "#33FF57", "#5733FF", "#FFFF33", "#33FFFF"];
const randomIndex = Math.floor(Math.random() * colors.length);
return colors[randomIndex];
}
function pointermoved(event) {
const [x, y] = d3.pointer(event);
nodes[0].fx = x - width / 2;
nodes[0].fy = y - height / 2;
for (let i = 1; i < nodes.length; ++i) {
const d = nodes[i];
const dx = d.x - x + width / 2;
const dy = d.y - y + height / 2;
const distanceToBoundary = Math.sqrt(dx ** 2 + dy ** 2) - d.r - nodes[0].r + forceDistance;
d.isTouchingBoundary = distanceToBoundary <= maxBoundaryDistance;
if (d.isTouchingBoundary) {
d.fadeStartTime = Date.now();
fadingNodes.push(d);
}
}
ticked();
}
function ticked() {
context.clearRect(0, 0, width, height);
context.save();
context.translate(width / 2, height / 2);
for (let i = 1; i < nodes.length; ++i) {
const d = nodes[i];
context.beginPath();
context.moveTo(d.x + d.r, d.y);
context.arc(d.x, d.y, d.r, 0, 2 * Math.PI);
if (fadingNodes.includes(d)) {
const elapsed = Date.now() - d.fadeStartTime;
const opacity = 1 - Math.min(elapsed * fadeOutRate, 1);
const interpolatedColor = d3.interpolateRgb(singleColor, boundaryColor)(opacity);
context.fillStyle = interpolatedColor;
} else {
context.fillStyle = singleColor;
}
context.fill();
}
context.restore();
}
return context.canvas;
}