toolkit/javascript/d3/examples/zoom/zoom.html
author Nicolas Sauret <nicolas.sauret@iri.centrepompidou.fr>
Thu, 10 Apr 2014 14:20:23 +0200
changeset 47 c0b4a8b5a012
permissions -rw-r--r--
add toolkit.html + démonstrateurs

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
    <title>Zoom</title>
    <script type="text/javascript" src="../../d3.js"></script>
    <script type="text/javascript" src="../../d3.csv.js"></script>
    <script type="text/javascript" src="../../d3.time.js"></script>
    <style type="text/css">

path {
  fill: steelblue;
}

line {
  stroke: #000;
  shape-rendering: crispEdges;
}

    </style>
  </head>
  <body>
    <script type="text/javascript">

var w = 960,
    h1 = 400,
    h2 = 40,
    p = 20,
    x0, // start of focus region
    x1, // end of focus region
    xx, // drag state
    time = d3.time.format("%Y-%m-%d"),
    x = d3.scale.linear().range([0, w]),
    y1 = d3.scale.linear().range([h1 - p, 0]),
    y2 = d3.scale.linear().range([h2, 0]);

var svg = d3.select("body")
  .append("svg:svg")
    .attr("width", w)
    .attr("height", h1 + h2);

// Focus view.
var focus = svg.append("svg:g");

// Context view.
var context = svg.append("svg:g")
    .attr("transform", "translate(0," + h1 + ")");

d3.csv("dji.csv", function(csv) {
  var minX,
      maxX,
      maxY = -Infinity;

  // Compute x- and y-extent.
  csv.reverse();
  for (var i = 0, n = csv.length, o; i < n; i++) {
    o = csv[i];
    o = csv[i] = {x: +time.parse(o.Date), y: +o.Close};
    if (o.y > maxY) maxY = o.y;
  }
  minX = csv[0].x;
  maxX = csv[n - 1].x;

  // Update x- and y-scales.
  x.domain([minX, maxX]);
  y1.domain([0, maxY]);
  y2.domain([0, maxY]);

  // Focus view.
  focus.append("svg:path")
      .data([csv])
      .attr("d", d3.svg.area()
      .x(function(d) { return x(d.x); })
      .y0(y1(0))
      .y1(function(d) { return y1(d.y); }));

  focus.append("svg:line")
      .attr("x1", 0)
      .attr("x2", w)
      .attr("y1", y1(0))
      .attr("y2", y1(0));

  // Context view.
  context.append("svg:rect")
      .attr("width", w)
      .attr("height", h2)
      .attr("fill", "none")
      .attr("pointer-events", "all")
      .attr("cursor", "crosshair")
      .on("mousedown", mousedown);

  context.append("svg:path")
      .data([csv])
      .attr("pointer-events", "none")
      .attr("d", d3.svg.area()
      .x(function(d) { return x(d.x); })
      .y0(y2(0))
      .y1(function(d) { return y2(d.y); }));

  context.append("svg:line")
      .attr("x1", 0)
      .attr("x2", w)
      .attr("y1", y2(0))
      .attr("y2", y2(0));

  // Active focus region.
  active = context.append("svg:rect")
      .attr("pointer-events", "none")
      .attr("id", "active")
      .attr("x", x(x0 = minX))
      .attr("y", 0)
      .attr("height", h2)
      .attr("width", x(x1 = (minX + 1e11)) - x(x0))
      .attr("fill", "lightcoral")
      .attr("fill-opacity", .5);
});

d3.select(window)
    .on("mousemove", mousemove)
    .on("mouseup", mouseup);

function mousedown() {
  xx = x.invert(d3.svg.mouse(this)[0]);
}

function mousemove() {
  if (xx != null) {

    // Compute the new (clamped) focus region.
    var xy = x.invert(d3.svg.mouse(active[0][0])[0]);
    if (xx < xy) { x0 = xx; x1 = xy; }
    else if (xx > xy) { x0 = xy; x1 = xx; }
    else return;
    x0 = Math.max(x.domain()[0], x0);
    x1 = Math.min(x.domain()[1], x1);

    // Update the x-scale. TODO Recycle this scale?
    var tx = d3.scale.linear()
        .domain([x0, x1])
        .range([0, w]);

    // Recompute the focus path.
    focus.select("path")
        .attr("d", d3.svg.area()
        .x(function(d) { return tx(d.x); })
        .y0(y1(0))
        .y1(function(d) { return y1(d.y); }));

    // Reposition the active region rect.
    active
        .attr("x", x(x0))
        .attr("width", x(x1) - x(x0));
  }
}

function mouseup() {
  xx = null;
}

    </script>
  </body>
</html>