block by curran b8e76dd7003538975b3e81e86ac6dd1e

Margin Convention with ReactiveModel

Full Screen


The data flow graph for this example (made with graph-diagrams).

This example shows dynamic margins for data visualizations using D3 4.0 and ReactiveModel. To experience the resize behavior, run this example full-screen and resize the browser. Based on the original D3 example Margin Convention. Part of a series of examples demonstrating ReactiveModel.

forked from curran‘s block: Responding to Resize with ReactiveModel

forked from curran‘s block: Margin Convention with Model.js

Built with blockbuilder.org

web counter

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Margin Convention with ReactiveModel</title>
    <script src="//d3js.org/d3.v4.0.0-alpha.49.min.js"></script>
    <script src="//datavis-tech.github.io/reactive-model/reactive-model-v0.11.0.min.js"></script>
    <style>

      /* Make the chart container fill the page using CSS. */
      #chart-container {
        position: fixed;
        left: 0px;
        right: 0px;
        top: 0px;
        bottom: 0px;
      }
    </style>
  </head>
  <body>

    <!-- The SVG graphics will be injected into this div. -->
    <div id="chart-container"></div>

    <script>
      
      // The constructor for a "margin visualization" component.
      // Renders a gray rectangle to show the configured margin.
      function MarginVis(){
        return ReactiveModel()
          ("width", 100)
          ("height", 100)
          ("svg")
          ("marginTop", 50)
          ("marginBottom", 50)
          ("marginLeft", 50)
          ("marginRight", 50)
        
          ("svg-width", function (svg, width){
            svg.attr("width", width);
          }, "svg, width")
        
          ("svg-height", function (svg, height){
            svg.attr("height", height);
          }, "svg, height")
        
          ("innerWidth", function (width, marginLeft, marginRight){
            return width - marginLeft - marginRight;
          }, "width, marginLeft, marginRight")
        
          ("innerHeight", function (height, marginTop, marginBottom){
            return height - marginTop - marginBottom;
          }, "height, marginTop, marginBottom")
        
          ("g", function (svg){
            return svg.append("g");
          }, "svg")
        
          ("g-transform", function (g, marginLeft, marginTop){
            g.attr("transform", "translate(" + marginLeft + "," + marginTop + ")");
          }, "g, marginLeft, marginTop")
        
          ("rect", function (g){
            return g.append("rect")
              .attr("fill", "lightgray")
              .attr("stroke", "gray");
          }, "g")
        
          ("rect-width", function (rect, innerWidth){
            rect.attr("width", innerWidth);
          }, "rect, innerWidth")
        
          ("rect-height", function (rect, innerHeight){
            rect.attr("height", innerHeight);
          }, "rect, innerHeight");
      }
      
      // The main program that uses the MarginVis component.
      function main(){
        
        // Set up the MarginVis instance.
        var container = d3.select("#chart-container"),
            marginVis = MarginVis()
              .svg(container.append("svg"));

        // Respond to resize.
        function resize(){
          marginVis
            .width(container.node().clientWidth)
            .height(container.node().clientHeight);
        }
        resize();
        window.addEventListener("resize", resize);
        
        // Change the margins around in a funky way.
        var time = 0;
        requestAnimationFrame(function updateMargin(){
          time += 0.01;
          
          marginVis
            .marginLeft(  (Math.sin(time     ) + 1.2) * 100)
            .marginRight( (Math.sin(time * 2 ) + 1.2) * 100)
            .marginTop(   (Math.sin(time * 3 ) + 1.5) * 50)
            .marginBottom((Math.sin(time * 4 ) + 1.5) * 50);
          
          requestAnimationFrame(updateMargin);
        });
      }
      main();
      
      // Output the data flow graph as JSON for visualization.
      console.log(JSON.stringify(ReactiveModel.serializeGraph(), null, 2));
    </script>
  </body>
</html>