{
regenerate;
const maxFrame = 400,
image = await (upload ?? FileAttachment("steven@1.jpeg")).image(),
width = image.width * scale,
height = image.height * scale,
imageData = getImageDate(image),
{ normal, darker, brighter } = filterColor(cm.random()),
color = createColor(imageData, width, height),
scaleColor = (d) => gray(color(d)),
scaleLength = cm.scaleLinear([0, maxFrame], [80, 5]),
scaleWeight = cm.scaleLinear([0, maxFrame], [1, 0.1]),
scaleRotate = cm.scaleLinear([0, 1], [-Math.PI, Math.PI]),
SO = {
x: (d) => -d.length / 2,
x1: (d) => d.length / 2,
strokeWidth: (d) => d.weight,
strokeCap: "round"
};
function update(app) {
const frameCount = app.prop("frameCount");
const points = cm.range(40).map(() => ({
x: cm.randomInt(width),
y: cm.randomInt(height)
}));
const groups = app
.data(points)
.process(cm.derive, {
color: scaleColor,
length: scaleLength(frameCount),
weight: scaleWeight(frameCount) * cm.randomInt(2, 15)
})
.process(cm.derive, {
rotate: (d) => scaleRotate(d3.hsl(d.color).l)
})
.append(cm.group, {
x: (d) => d.x,
y: (d) => d.y,
rotate: (d) => d.rotate
});
if (frameCount % 3 === 0) {
groups.append(cm.link, {
...SO,
x: 0,
y: 0,
x1: 5,
y1: 0,
stroke: normal
});
} else {
groups
.call((d) => d.append(cm.link, { ...SO, y: 1, y1: 1, stroke: darker }))
.call((d) => d.append(cm.link, { ...SO, y: 0, y1: 0, stroke: normal }))
.call((d) =>
d.append(cm.link, { ...SO, y: 2, y1: 2, stroke: brighter })
);
}
if (frameCount > maxFrame) app.stop();
}
function dispose(app) {
invalidation.then(() => app.dispose());
}
return cm
.app({ width, height })
.on("update", update)
.call(dispose)
.start()
.node();
}