Home Examples Documentation Playground Source

Stardust Example: Daily Activities of Creative People

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<link rel="stylesheet" href="../static/assets/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="../static/stardust/stardust.bundle.min.js" type="text/javascript"></script>
<script src="../static/assets/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>