D3.js

データビジュアライゼーションのためのD3.js徹底入門 Webで魅せるグラフ&チャートの作り方

データビジュアライゼーションのためのD3.js徹底入門 Webで魅せるグラフ&チャートの作り方

第11章 ヒストグラム まで。 ここまでくると、お決まりの svgWidth などを毎回書くのがムダに思える。JavaScript があまり良くわかってないけど、外だしにできないのかなぁ・・・。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>SVG</title>

    <link href="../node_modules/bootstrap/dist/css/bootstrap-theme.min.css" rel="stylesheet">
    <link href="../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="../node_modules/octicons/octicons/octicons.css" rel="stylesheet">

    <!--[if lt IE 9]>
      <script src="https://cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.min.js"></script>
      <script src="https://cdn.jsdelivr.net/respond/1.4.2/respond.min.js"></script>
    <![endif]-->

    <style media="screen">
      .axis text {
        font-family: sans-serif;
        font-size: 11px;
      }
      .axis path, .axis line {
        fill: none;
        stroke: black;
      }
      .bar { fill: #aaa; stroke: white; stroke-width: 1; }
      svg { width: 380px; height: 300px; border: 1px solid; background-image: url(images/bg.png)}
    </style>
  </head>
  <body>
    <script src="../node_modules/jquery/dist/jquery.min.js" charset="utf-8"></script>
    <script src="../node_modules/bootstrap/dist/js/bootstrap.min.js" charset="utf-8"></script>
    <script src="../node_modules/d3/d3.min.js" charset="utf-8"></script>

    <div class="container">
      <h1>ヒストグラムを表示</h1>
      <div class="row">
        <div class="col-sm-4">
          <svg id="myGraph1"></svg>
          <form id="dataSelect">
            <input type="button" class="btn btn-primary btn-sm" data-grader="g1" value="1年性">
            <input type="button" class="btn btn-primary btn-sm" data-grader="g2" value="2年性">
            <input type="button" class="btn btn-primary btn-sm" data-grader="g3" value="3年性">
            <input type="button" class="btn btn-primary btn-sm" data-grader="g4" value="4年性">
            <input type="button" class="btn btn-primary btn-sm" data-grader="g5" value="5年性">
            <input type="button" class="btn btn-primary btn-sm" data-grader="g6" value="6年性">
            <div class="form-inline">
              <p>
                間隔: <input class="form-control input-sm" type="text" value="10" id="step">
              </p>
            </div>
          </form>
        </div>
        <div class="col-sm-4">
        </div>
        <div class="col-sm-4">
        </div>
      </div>
      <script src="sample11.js" charset="utf-8"></script>
    </div>
  </body>
</html>
d3.csv("sample11/mydata.csv", function(error, data) {
  var svgEle = document.getElementById("myGraph1");
  var svgWidth = parseFloat(window.getComputedStyle(svgEle, null).getPropertyValue("width"));
  var svgHeight = parseFloat(window.getComputedStyle(svgEle, null).getPropertyValue("height"));
  var xAxisWidth = svgWidth - 40;
  var yAxisHeight = svgHeight - 30;
  var offsetX = 30;
  var offsetY = 10;
  var stepX = 10;
  var xScale;
  var yScale;
  var barWidth = svgWidth / 11;

  // var dataset = [
  //   50, 95, 60, 44, 60, 50, 35, 20, 10, 8,
  //   56, 70, 65, 42, 22, 33, 40, 53, 52, 89,
  //   90, 55, 50, 55, 65, 72, 45, 35, 15, 45
  // ];

  var dataset = [];
  data.forEach(function(d, i) {
    dataset.push(d.g1);
  });

  var histogram = d3.layout.histogram()
    .range([0, 100])
    .bins(d3.range(0, 100.1, stepX));

  function calcScale() {
    var maxValue = d3.max(histogram(dataset), function(d, i) {
      return d.y;
    });

    yScale = d3.scale.linear()
      .domain([0, maxValue])
      .range([yAxisHeight, 0]);

    xScale = d3.scale.linear()
      .domain([0, 100])
      .range([0, xAxisWidth]);
  }

  // 目盛りを表示
  function drawScale() {
    d3.select("#myGraph1")
      .append("g")
      .attr("class", "axis")
      .attr("transform", "translate(" + offsetX + ", " + offsetY + ")")
      .call(
        d3.svg.axis()
          .scale(yScale)
          .orient("left")
      );

    d3.select("#myGraph1")
      .append("g")
      .attr("class", "axis")
      .attr("transform", "translate(" + offsetX + ", " + (yAxisHeight + offsetY) + ")")
      .call(
        d3.svg.axis()
          .scale(xScale)
          .orient("bottom")
      );
  }

  function drawHistgram() {
    var barElements = d3.select("#myGraph1")
      // .selectAll("rect")
      .selectAll("imagee")
      .data(histogram(dataset))
      .enter()
      // .append("rect")
      .append("image")
      .attr("class", "bar")
      .attr("xlink:href", "images/man.png")
      .attr("width", function(d, i) {
        return xScale(d.dx);
      })
      .attr("x", function(d, i) {
        return i * xScale(d.dx) + offsetX;
      })
      .attr("y", yAxisHeight + offsetY)
      .attr("height", 0)
      .transition()
      .duration(1000)
      .attr("y", function(d, i) {
        return yScale(d.y) + offsetY;
      })
      .attr("height", function(d, i) {
        return yAxisHeight - yScale(d.y);
      });
  }

  // 間隔が変更されたらヒストグラムを更新
  d3.select("#step").on("change", function() {
    stepX = this.value;
    histogram.bins(d3.range(0, 100.1, stepX));
    d3.select("#myGraph1").selectAll("*").remove();
    calcScale();
    drawHistgram();
    drawScale();
  });

  // 初期表示
  calcScale();
  drawHistgram();
  drawScale();

  d3.select("#dataSelect").selectAll("input[type='button']")
    .on("click", function() {
      var grader = d3.select(this).attr("data-grader");
      dataset = [];
      data.forEach(function(d, i) {
        dataset.push(d[grader]);
      });
      d3.select("#myGraph1").selectAll("*").remove();
      calcScale();
      drawHistgram();
      drawScale();
    });
});

f:id:yossk:20150614083024j:plain