viewof chart = {
const engine = Matter.Engine.create({
positionIterations: 10,
constraintIterations: 10
});
const world = engine.world;
world.gravity.y = 0;
Matter.World.add(world, initialBodies);
const pathFunc = d3
.line()
.x((d) => d.x)
.y((d) => d.y);
const destination = {
x: width / 2,
y: height / 2
};
const strength = 0.03;
const velocityDecay = 0.2;
Matter.Events.on(engine, "beforeUpdate", () => {
Matter.Composite.allBodies(world).forEach((body) => {
const { position } = body;
const distance = Matter.Vector.sub(destination, position);
body._vx = ((body._vx || 0) + distance.x * xStrength) * velocityDecay;
body._vy = ((body._vY || 0) + distance.y * yStrength) * velocityDecay;
Matter.Body.setVelocity(body, {
x: body._vx,
y: body._vy
});
let angle = radToDeg(body.angle);
angle = Math.max(-maxAngle, angle);
angle = Math.min(maxAngle, angle);
Matter.Body.setAngle(body, degToRad(angle));
});
});
let tick = 0;
let running = true;
window.stop = () => {
running = false;
};
while (running) {
tick++;
Matter.Engine.update(engine, 1000 / 60);
const bodies = Matter.Composite.allBodies(world);
const paths = bodies.map((body, index) => {
const { vertices, position, angle } = body;
const pathData = `${pathFunc(vertices)}z`;
const style = `fill: black; fill-opacity: 0.03; stroke: black; stroke-width: 1px; stroke-opacity: 0.7`;
const degrees = radToDeg(angle);
const transform = `translate(${position.x}, ${position.y}) rotate(${degrees})`;
const textStyle = `font-size: 0.8rem; font-family: sans-serif; alignment-baseline: middle; text-anchor: middle;`;
let path = null;
if (showOvals) {
path = `<path d="${pathData}" style="${style}"></path>`;
}
return `
<g>
${path}
<text transform="${transform}" style="${textStyle}">${body.name}</text>
</g>
`;
});
const style = `height: ${height}px; width: ${width}px; shape-rendering: geometricPrecision;`;
yield html`<svg style="${style}">${paths}</svg>`;
}
}