Skip to content

Instantly share code, notes, and snippets.

@freddi301
Created May 21, 2019 09:39
Show Gist options
  • Save freddi301/e97649d0123a3bfc1eafad7e0febc517 to your computer and use it in GitHub Desktop.
Save freddi301/e97649d0123a3bfc1eafad7e0febc517 to your computer and use it in GitHub Desktop.
Force simulation
const ns = [
{ name: "a", x: 200.01, y: 200.01 },
{ name: "b", x: 220, y: 220 },
{ name: "c", x: 180, y: 200.01 },
{ name: "d", x: 182, y: 201 },
{ name: "e", x: 230, y: 170 },
{ name: "f", x: Math.random() * 400, y: Math.random() * 400 },
{ name: "g", x: Math.random() * 400, y: Math.random() * 400 },
];
function Simulation() {
const nodes = useSimulation(ns);
return (
<svg width={400} height={400}>
{nodes.map(node => (
<circle key={node.name} r={5} cx={node.x} cy={node.y} fill="black" />
))}
</svg>
);
}
function useSimulation(
initialNodes: Array<{ name: string; x: number; y: number }>,
) {
const [nodes, setNodes] = React.useState(initialNodes);
React.useEffect(() => {
const id = setInterval(
() =>
setNodes(nodes => {
return nodes.map(node => {
return [
...nodes.map(n => {
if (n === node) {
return { x: 0, y: 0 };
}
const dir = direction(node, n);
const dis = distance(node, n);
const int = dis >= 100 ? 0 : (100 - dis) * 0.05;
const x = (node.x < n.x ? -1 : 1) * Math.cos(dir) * int;
const y = (node.y < n.y ? -1 : 1) * Math.sin(dir) * int;
return { x, y };
}),
// (n => {
// const dir = direction(node, n);
// const dis = distance(node, n);
// const int = dis * 0.01 * -1;
// const x = (node.x < n.x ? -1 : 1) * Math.cos(dir) * int;
// const y = (node.y < n.y ? -1 : 1) * Math.sin(dir) * int;
// return { x, y };
// })({ x: 200, y: 200 }),
...nodes.map(n => {
if (n === node) {
return { x: 0, y: 0 };
}
const dir = direction(node, n);
const dis = distance(node, n);
const int = dis < 100 ? 0 : (dis - 100) * 0.05 * -1;
const x = (node.x < n.x ? -1 : 1) * Math.cos(dir) * int;
const y = (node.y < n.y ? -1 : 1) * Math.sin(dir) * int;
return { x, y };
}),
].reduce<{ name: string; x: number; y: number }>(
(memo, { x, y }) => ({
...memo,
x: memo.x + x,
y: memo.y + y,
}),
node,
);
});
}),
17,
);
return () => clearInterval(id);
}, []);
return nodes;
}
function distance(m: { x: number; y: number }, n: { x: number; y: number }) {
return Math.sqrt((m.x - n.x) ** 2 + (n.y - m.y) ** 2);
}
function direction(m: { x: number; y: number }, n: { x: number; y: number }) {
return Math.atan((m.y - n.y) / (m.x - n.x));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment