Archived

Documentation for Layer Cake v10, before Svelte 5 runes. Current docs at layercake.graphics

Menu

WebGL Scatter (svg axes, quadtree hover)

1980
1985
1990
1995
2000
2005
2010
2015
4
5
6
7

A scatter plot drawn with WebGL, with HTML axes and a QuadTree layer that marks the nearest point on hover.

This is the server-side rendered version. ssr and percentRange on <LayerCake> put the scales in percentages, so the chart renders before the browser measures it. The axes are HTML components, and the WebGL layer draws once the page is in the browser.

<script>
  import { LayerCake, WebGL, Html } from 'layercake';

  import ScatterWebgl from './_components/Scatter.webgl.svelte';
  import AxisX from './_components/AxisX.percent-range.html.svelte';
  import AxisY from './_components/AxisY.percent-range.html.svelte';
  import QuadTree from './_components/QuadTree.percent-range.html.svelte';

  // The CSV rows are parsed, and their numbers typed, by @rollup/plugin-dsv. See vite.config.js
  import data from './_data/points.csv';

  const xKey = 'myX';
  const yKey = 'myY';

  const r = 3;
  // In percent units, so smaller than the client-side version's 6 pixels
  const xyPadding = 2;
</script>

<div class="chart-container">
  <LayerCake
    ssr
    percentRange
    padding={{ top: 5, right: 5, bottom: 20, left: 25 }}
    x={xKey}
    y={yKey}
    xPadding={[xyPadding, xyPadding]}
    yPadding={[xyPadding, xyPadding]}
    {data}
  >
    <Html>
      <AxisX />
      <AxisY tickMarks={false} ticks={5} />
    </Html>

    <WebGL>
      <ScatterWebgl {r} />
    </WebGL>

    <Html>
      <QuadTree>
        {#snippet children({ x, y, visible })}
          <div
            class="circle"
            style="top:{y}%;left:{x}%;display: {visible ? 'block' : 'none'};"
          ></div>
        {/snippet}
      </QuadTree>
    </Html>
  </LayerCake>
</div>

<style>
  /* Give the wrapper a width and height. LayerCake fills it. */
  .chart-container {
    width: 100%;
    height: 250px;
  }
  .circle {
    position: absolute;
    border-radius: 50%;
    background-color: rgba(171, 0, 214);
    transform: translate(-50%, -50%);
    pointer-events: none;
    width: 10px;
    height: 10px;
  }
</style>