--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/toolkit/javascript/d3/examples/zoom/zoom.html Thu Apr 10 14:20:23 2014 +0200
@@ -0,0 +1,162 @@
+<!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>