Home Examples Documentation Playground Source

Stardust Example: Daily Activities of Creative People

index.html

<!DOCTYPE html>
<meta charset="utf-8" />
<link rel="stylesheet" href="../common/style.css" type="text/css" />
<canvas id="main-canvas"></canvas>
<div data-switch="mode">
  <button class="active" data-value="mode1">Circular</button><button data-value="mode2">Linear</button>
  <div class="fps"></div>
</div>
<div class="initializing"><p>Initializing...</p></div>
<script src="//d3js.org/d3.v3.min.js" type="text/javascript"></script>
<script src="../common/stardust/stardust.bundle.js" type="text/javascript"></script>
<script src="../common/utils.js" type="text/javascript"></script>
<script type="text/javascript">
  // Create Stardust platform from canvas element
  var canvas = document.getElementById("main-canvas");
  var width = 960;
  var height = 470;
  var platform = Stardust.platform("webgl-2d", canvas, width, height);

  // Create bar marks using wedge
  var barMark = Stardust.mark.compile(`
        import { Wedge } from P2D;

        mark Bar(
            index: float,
            center: Vector2,
            vcenter: Vector2,
            radius: float,
            t1: float,
            t2: float,
            t: float,
            width: float,
            width2: float,
            color: Color = [ 0, 0, 0, 1 ]
        ) {
            let thetaA = (t1 - 6) / 12.0 * PI;
            let thetaB = (t2 - 6) / 12.0 * PI;
            let cP1 = center + Vector2(cos(thetaA), sin(thetaA)) * radius;
            let k = 1.5;
            if(t1 + t2 < 12) k = -0.5;
            let ss = 2;
            let ti = t * (1 + ss) - ss + (1 - index) * ss;
            if(ti < 0) ti = 0;
            if(ti > 1) ti = 1;
            Wedge(
                mix(cP1, vcenter + Vector2(t1 * 38, 0), ti),
                mix(thetaA, PI * k, ti),
                mix(thetaB, PI * k, ti),
                mix(radius * (thetaB - thetaA), (t2 - t1) * 38, ti),
                mix(width2, width, ti),
                color
            );
        }
    `);

  // Create bars with our barMark
  var bars = Stardust.mark.create(barMark.Bar, platform);

  // Use D3's scale for colors
  var colorScale = d3.scale.category10();

  loadData("data.json", data => {
    // Layout parameters
    let yScale = d3.scale
      .linear()
      .domain([0, data.length - 1])
      .range([15, height - 15]);
    let h = (yScale(1) - yScale(0)) * 0.8;
    let sz = Math.sqrt(((width - 15) * (height - 15)) / data.length / 5);
    let grouping = Math.floor(width / sz / 2);

    // Attributes
    bars.attr("t", 0);
    bars.attr("t1", d => d.start);
    bars.attr("t2", d => d.start + d.duration);
    bars.attr("color", d => Stardust.Color.FromHTML(colorScale(d.type)));
    bars.attr("width", h);
    bars.attr("width2", sz * 0.3);

    // Instancing
    bars.instance(
      d => d.activities,
      (d, i) => {
        return {
          index: i / (data.length - 1),
          center: [(i % grouping) * sz * 2 + sz + 4, Math.floor(i / grouping) * sz * 2 + sz + 10],
          radius: sz - (sz * 0.3) / 2 - 2,
          vcenter: [20, yScale(i)]
        };
      }
    );

    // Set data items to bars
    bars.data(data);

    // Render/Re-render bars
    function render() {
      platform.clear();
      bars.render();
    }

    render();

    // Handle switches and animation timing
    switches.mode_changed = function(newValue) {
      beginTransition(t => {
        if (newValue == "mode1") bars.attr("t", 1 - t);
        if (newValue == "mode2") bars.attr("t", t);
        render();
      });
    };
  });
</script>