block by curran 9f5b38ca4fb8f7cf7af461973a1407c6

React + D3 Boilerplate

Full Screen

Boilerplate D3 + React integration.

Features:

Inspired by:

I’m new to React and I’m not sure if everything I’ve done here is “the react way”. If you see something questionable please let me know on Twitter.

Many thanks to @DatMousse for this refactor proposal.

Built with blockbuilder.org

forked from curran‘s block: React Boilerplate

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React + D3!</title>
    
    <!-- React -->
    <script src="//npmcdn.com/react@15.3.0/dist/react.min.js"></script>
    <script src="//npmcdn.com/react-dom@15.3.0/dist/react-dom.min.js"></script>
    <script src="//npmcdn.com/babel-core@5.8.38/browser.min.js"></script>
    
    <!-- D3 -->
    <script src="//d3js.org/d3.v4.min.js"></script>
    
    <style>

      /* Make the chart container fill the page using CSS. */
      #chart {
        position: fixed;
        left: 0px;
        right: 0px;
        top: 0px;
        bottom: 0px;
      }
    </style>
    
  </head>
  <body>
    
    <div id="chart"></div>
    
    <script type="text/babel">
      
      var MyD3Vis = React.createClass({
        
        render: function() {
          return (
            <div>
              <svg width={this.props.width}
                   height={this.props.height}
                   ref="container">
              </svg>
            </div>
          );
        },
        
        componentDidMount: function() {
          this.container = d3.select(ReactDOM.findDOMNode(this.refs.container));
          
          this.shouldComponentUpdate(this.props);
          
          this.interval = setInterval(function (){
            console.log("D3 graphic active at " + new Date());
          }, 1000);
        },
        
        shouldComponentUpdate() {
          this.renderCircles();
          this.renderLines();
        },
        
        renderCircles: function (){
          var circles = this.container
            .selectAll("circle")
              .data(this.props.data);
          circles.exit().remove();
          circles
            .enter().append("circle")
              .attr("r", 50)
            .merge(circles)
              .transition().duration(800)
              .attr("cx", function (d){ return d.x; })
              .attr("cy", function (d){ return d.y; });
        },
        
        renderLines: function (){
          var {width, height} = this.props;
          var lines = this.container.selectAll("line").data([
            {x1: 0, y1: 0, x2: width, y2: height},
            {x1: 0, y1: height, x2: width, y2: 0}
          ]);
          lines.enter()
            .append("line")
              .style("stroke-width", 50)
              .style("stroke-opacity", 0.4)
              .style("stroke", "black")
            .merge(lines)
              .attr("x1", function (d) { return d.x1; })
              .attr("y1", function (d) { return d.y1; })
              .attr("x2", function (d) { return d.x2; })
              .attr("y2", function (d) { return d.y2; });
        },
        componentWillUnmount: function (){
          clearInterval(this.interval);
        }
      });
      
      var width = 200,
          height = 200,
          data = [
            { x: 50, y: 50 },
            { x: 100, y: 100 }
          ],
          show = true;
      
      function render(){
        
        var chartDiv = document.getElementById("chart");
        
        width = chartDiv.clientWidth;
        height = chartDiv.clientHeight;
        
        if(show){
          ReactDOM.render(
            <MyD3Vis width={width} height={height} data={data} />,
            chartDiv
          );
        } else {
          ReactDOM.render(
            <h1>Press any key to show graphic.</h1>,
            chartDiv
          );
        }
        
      }
      
      render();
      
      setInterval(function (){
        data[0].x = Math.round(Date.now() / 50 % width);
        data[0].y = Math.round(Date.now() / 10 % height);
        data[1].x = Math.round(Date.now() / 60 % width);
        data[1].y = Math.round(Date.now() / 70 % height);
        render();
      }, 1000);
      
      window.addEventListener("resize", render);
      
      window.addEventListener("keyup", function(){
        show = !show;
        render();
      });
    </script>
  </body>
</html>