Example: Canvas Scatterplot

This example illustrates how to use basic marks and attributes to animate the x, y, and color properties of a set of point marks. When you click the Animate button, all points change color, while half the points simultaneously change x-coordinates. When you click the Animate button more than once in succession, the points animate from their current locations.

import('https://cdn.jsdelivr.net/npm/counterpoint-vis@latest/dist/counterpoint-vis.es.js').then((counterpoint) => {
  // canvas setup
  const canvas = document.getElementById("scatterplot-canvas");
  canvas.width = canvas.offsetWidth * window.devicePixelRatio;
  canvas.height = canvas.offsetHeight * window.devicePixelRatio;

  // increments when the user clicks the button
  let colorIdx = 0;

  // initialize the render group with 100 marks
  let markSet = new counterpoint.MarkRenderGroup(
    new Array(100).fill(0).map(
      (_, i) =>
        new counterpoint.Mark(i, {
          x: Math.random() * 500,
          y: Math.random() * 500,
          color: () => (colorIdx % 2 == 0 ? '#9f1239' : '#4338ca')
        })
    )
  );

  // Animate button event handler
  document.getElementById('animate-button').addEventListener('click', () => {
    // when the button is clicked, alternate the color and move half the points' x coordinate
    colorIdx += 1;
    markSet
      .animate('color')
      .filter((m) => m.id % 2 == 0)
      .animateTo('x', (m) => (m.attr('x') + 100) % 500, {
        delay: (m) => m.id * 10,
      });
  });

  // drawing function that will get called by the Ticker every time a redraw is needed
  function draw() {
    if (!!canvas) {
      let ctx = canvas.getContext('2d');

      if (!!ctx) {
        ctx.resetTransform();
        ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
        ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
        ctx.strokeStyle = 'white';
        ctx.lineWidth = 1.0;
        markSet.stage.forEach((mark) => {
          let x = mark.attr('x');
          let y = mark.attr('y');
          let color = mark.attr('color');
          ctx.fillStyle = color;
          ctx?.beginPath();
          ctx?.ellipse(x, y, 5, 5, 0, 0, 2 * Math.PI, false);
          ctx?.fill();
          ctx?.stroke();
          ctx?.closePath();
        });
      }
    }
  }

  let ticker = new counterpoint.Ticker(markSet).onChange(draw);
  draw();
});

results matching ""

    No results matching ""