Interaction Design WikiWeb Development

Scrollable Visualization

The following example implements a scrollable d3.js visualization using ScrollMagic.js.

Create an index.html with the following content:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script src="https://fastcdn.org/ScrollMagic/2.0.5/minified/ScrollMagic.min.js"></script>
    <style media="screen">
      html, body {
        height: 100%;
        margin: 0;
      }
      .pane {
        width: 100%;
        height: 100%;
        background-color: #eee;
      }
      .pane.a { background-color: tomato; }
      .pane.b { background-color: #ddd; }
      .pane.c { background-color: steelblue; }
    </style>
  </head>
  <body>
    <div class="pane a">
    </div>
    <div class="pane b">
      <svg class="canvas">
      </svg>
    </div>
    <div class="pane c">
    </div>

    <script type="text/javascript">
      // set SVG to full width and height
      var canvas = d3.select('.canvas')
        .attr('width', window.innerWidth)
        .attr('height', window.innerHeight);

      // create the scales for the full width and height
      var xScale = d3.scaleLinear()
        .range([150, window.innerWidth - 150]);
      var yScale = d3.scaleLinear()
        .range([150, window.innerHeight - 150]);

      // create the circle
      var circle = d3.select('.canvas')
        .append('circle')
        .attr('r', 100);

      // our custom function to position the circle
      function setCircle(progress) {
        circle.attr('cx', xScale(progress));
        circle.attr('cy', yScale(progress));
      }

      // make initial positioning
      setCircle(0);

      // create a scroll magic controller
      var controller = new ScrollMagic.Controller();

      // create a scene
      new ScrollMagic.Scene({
          // the element to scroll inside
          triggerElement: '.pane.b',
          // how many pixels do we scroll
          duration: window.innerHeight * 2,
          // set trigger to top
          triggerHook: 'onLeave'
        })
        // pins the element for the the scene's duration
        .setPin('.pane.b')
        // assign the scene to the controller
        .addTo(controller)
        // subscribe to progress events
        .on('progress', function(e) {
          // position the circle accordingly
          setCircle(e.progress);
        });
    </script>
  </body>
</html>