<script>
import { LayerCake, Svg } from 'layercake';
import { scaleOrdinal, scaleBand } from 'd3-scale';
import ForceLayout from './_components/CirclePackForce.svelte';
import data from './_data/dots.json';
const xKey = 'category';
const rKey = 'value';
const zKey = 'category';
let groupBy = 'true';
const seriesColors = ['#f0c', '#0cf', '#fc0'];
let manyBodyStrength = 3;
let xStrength = 0.1
</script>
<style>
.chart-container {
width: 100%;
height: 250px;
}
label {
cursor: pointer;
}
input {
margin-right: 7px;
}
</style>
<div class="input-container">
<label><input type="radio" bind:group={groupBy} value="true"/>Group by category</label>
<label><input type="radio" bind:group={groupBy} value="false"/>Clump together</label>
</div>
<div class="chart-container">
<LayerCake
data={data}
x={xKey}
r={rKey}
z={zKey}
xScale={scaleBand()}
rRange={[3, 12]}
zScale={scaleOrdinal()}
zRange={seriesColors}
>
<Svg>
<ForceLayout
{manyBodyStrength}
{xStrength}
groupBy={JSON.parse(groupBy)}
nodeStroke='#000'
/>
</Svg>
</LayerCake>
</div>
<script>
import { getContext } from 'svelte';
import {
forceSimulation,
forceX,
forceManyBody,
forceCollide,
forceCenter,
} from 'd3-force';
const { data, width, height, xScale, xGet, rGet, zGet } = getContext('LayerCake');
export let manyBodyStrength = 5;
export let xStrength = 0.1;
export let nodeColor = undefined;
export let nodeStroke = '#fff';
export let nodeStrokeWidth = 1;
export let groupBy = true;
const initialNodes = $data.map((d) => ({ ...d }));
const simulation = forceSimulation(initialNodes)
let nodes = [];
simulation.on("tick", () => {
nodes = simulation.nodes()
})
$: {
simulation
.force('x', forceX().x(d => {
return groupBy === true ? $xGet(d) + $xScale.bandwidth() / 2 : $width / 2;
}).strength(xStrength))
.force('center', forceCenter($width / 2, $height / 2))
.force('charge', forceManyBody().strength(manyBodyStrength))
.force('collision', forceCollide().radius(d => {
return $rGet(d) + nodeStrokeWidth / 2;
}))
.force('center', forceCenter($width / 2, $height / 2))
.alpha(1)
.restart()
}
</script>
{#each nodes as point}
<circle
class='node'
r={$rGet(point)}
fill={nodeColor || $zGet(point)}
stroke={nodeStroke}
stroke-width={nodeStrokeWidth}
cx='{point.x}'
cy='{point.y}'
>
</circle>
{/each}
[
{ "category": "a", "value": 0 },
{ "category": "a", "value": 2 },
{ "category": "a", "value": 5 },
{ "category": "a", "value": 23 },
{ "category": "a", "value": 12 },
{ "category": "a", "value": 50 },
{ "category": "a", "value": 7 },
{ "category": "a", "value": 20 },
{ "category": "a", "value": 15 },
{ "category": "a", "value": 30 },
{ "category": "a", "value": 2 },
{ "category": "b", "value": 10 },
{ "category": "b", "value": 12 },
{ "category": "b", "value": 15 },
{ "category": "b", "value": 3 },
{ "category": "b", "value": 2 },
{ "category": "b", "value": 5 },
{ "category": "b", "value": 35 },
{ "category": "b", "value": 2 },
{ "category": "b", "value": 5 },
{ "category": "b", "value": 20 },
{ "category": "b", "value": 12 },
{ "category": "c", "value": 5 },
{ "category": "c", "value": 4 },
{ "category": "c", "value": 2 },
{ "category": "c", "value": 32 },
{ "category": "c", "value": 25 },
{ "category": "c", "value": 40 },
{ "category": "c", "value": 35 },
{ "category": "c", "value": 25 },
{ "category": "c", "value": 19 },
{ "category": "c", "value": 25 },
{ "category": "c", "value": 10 }
]