UNPKG

d3

Version:

A small, free JavaScript library for manipulating documents based on data.

163 lines (137 loc) 3.73 kB
<!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>