Menu

Beeswarm, force layoutEdit

A Beeswarm chart using a statically generated D3 force layout with a technique from @anmccartney. For a non-force layout Beeswarm see this example. For another way of doing a D3 force layout, see the Circle Pack Force example.

This chart is an example of using the slot prop let: width to set a dynamic circle radius based on the chart's width.

<script>
  import { LayerCake, Svg, Html } from 'layercake';
  import { scaleOrdinal } from 'd3-scale';

  import Key from './components/Key.svelte';
  import AxisX from './components/AxisX.svelte';
  import Beeswarm from './components/BeeswarmForce.svelte';

  // This example loads csv data as json using @rollup/plugin-dsv
  import data from './data/us-senate.csv';

  const xKey = 'date_of_birth';
  const zKey = 'gender';
  const titleKey = 'name';

  const r = 6;

  const seriesNames = new Set();
  const seriesColors = ['#fc0', '#000'];

  const dataTransformed = data.map(d => {
    seriesNames.add(d[zKey]);

    return {
      [titleKey]: d[titleKey],
      [zKey]: d[zKey],
      [xKey]: +d[xKey].split('-')[0]
    }
  })

</script>

<style>
  /*
    The wrapper div needs to have an explicit width and height in CSS.
    It can also be a flexbox child or CSS grid element.
    The point being it needs dimensions since the <LayerCake> element will
    expand to fill it.
  */
  .chart-container {
    width: 100%;
    height: 100%;
  }
</style>

<div class='chart-container'>
  <LayerCake
    padding={{bottom: 15}}
    x={xKey}
    z={zKey}
    zScale={scaleOrdinal()}
    zDomain={Array.from(seriesNames)}
    zRange={seriesColors}
    data={dataTransformed}
    custom={{
      getTitle: d => d[titleKey]
    }}
    let:width
  >

    <Svg>
      <AxisX/>
      <Beeswarm
        r={width < 400 ? r / 1.25 : r}
        strokeWidth={1}
        xStrength={0.95}
        yStrength={0.075}
      />
    </Svg>

    <Html pointerEvents={false}>
      <Key shape='circle' />
    </Html>

  </LayerCake>
</div>