{
const width = 600,
height = 200,
car = object({
location: cm.vec(width / 2, height / 2),
maxSpeed: 2,
maxForce: 0.05,
r: 6,
wanderR: 25,
wanderD: 80,
wanderT: 0,
wanderC: 0.3
});
function update(app) {
app.append(cm.clear, { fill: cm.rgb(255) });
const groups = app
.datum(car)
.process(cm.each, target)
.process(cm.each, seek)
.process(cm.each, constrainX)
.process(cm.each, constrainY)
.process(cm.each, move);
groups.append(cm.circle, {
x: (d) => d.circle.x,
y: (d) => d.circle.y,
r: (d) => d.wanderR,
fill: cm.rgb(255),
stroke: cm.rgb(0)
});
groups.append(cm.link, {
x: (d) => d.circle.x,
y: (d) => d.circle.y,
x1: (d) => d.location.x,
y1: (d) => d.location.y
});
groups.append(cm.circle, {
x: (d) => d.target.x,
y: (d) => d.target.y,
r: 2,
fill: cm.rgb(175),
stroke: cm.rgb(0)
});
groups.append(cm.link, {
x: (d) => d.circle.x,
y: (d) => d.circle.y,
x1: (d) => d.target.x,
y1: (d) => d.target.y
});
groups
.append(cm.group, {
x: (d) => d.location.x,
y: (d) => d.location.y,
rotate: (d) => d.velocity.angle()
})
.append(cm.triangle, {
x: (d) => d.r * 2,
y: 0,
x1: (d) => -d.r * 2,
y1: (d) => -d.r,
x2: (d) => -d.r * 2,
y2: (d) => d.r,
fill: cm.rgb(175),
stroke: cm.rgb(0),
strokeWidth: 2
});
}
function dispose(app) {
invalidation.then(() => app.dispose());
}
return cm
.app({ width, height })
.on("update", update)
.call(border)
.call(dispose)
.start()
.node();
}