title: d3JS: Plot lower-density data version of a large data set when zoomed out on line/area chart
body: <p>I'm creating a chart similar to <a href="http://mbostock.github.io/d3/talk/20111018/area-gradient.html" rel="nofollow">Mike Bostock's</a> zoomable area chart.</p>
  
  <p>For my specific project, I have a bunch of sensors which are recording values every 30 seconds (temperature, light, humidity and sound).  I have the zoom implementation working, however when I zoom out to the scale of, say, a year, the density of the chart slows downs the browser and the graphics don't read as well.</p>
  
  <p>How can I edit the script so that the density of the line graph changes relative to the amount of zoom?  In other words, the x domain is controlling the number of points on the valueline.  I'd like to have full density (a recording every 30 seconds) when I zoom in to a time range of one hour, and I'd like much lower density (a recording every day) when I zoom out.  Any ideas?  An implementation with the script from the link above would be helpful.</p>
  
  <p>Thanks!</p>
  
  <pre><code>    &lt;!DOCTYPE html&gt;
      &lt;html&gt;
        &lt;head&gt;
          &lt;meta http-equiv="Content-Type" content="text/html;charset=utf-8"/&gt;
          &lt;script type="text/javascript" src="d3/d3.js"&gt;&lt;/script&gt;
          &lt;script type="text/javascript" src="d3/d3.csv.js"&gt;&lt;/script&gt;
          &lt;script type="text/javascript" src="d3/d3.time.js"&gt;&lt;/script&gt;
          &lt;link type="text/css" rel="stylesheet" href="style.css"/&gt;
          &lt;style type="text/css"&gt;
  
      svg {
        font-size: 10px;
      }
  
      .axis {
        shape-rendering: crispEdges;
      }
  
      .axis path, .axis line {
        fill: none;
        stroke-width: .5px;
      }
  
      .x.axis path {
        stroke: #000;
      }
  
      .x.axis line {
        stroke: #fff;
        stroke-opacity: .5;
      }
  
      .y.axis line {
        stroke: #ddd;
      }
  
      path.line {
        fill: none;
        stroke: #000;
        stroke-width: .5px;
      }
  
      rect.pane {
        cursor: move;
        fill: none;
        pointer-events: all;
      }
  
          &lt;/style&gt;
        &lt;/head&gt;
        &lt;body&gt;
          &lt;div id="body"&gt;
            &lt;div id="footer"&gt;
              &lt;span&gt;…&lt;/span&gt;
              &lt;div class="hint"&gt;mousewheel to zoom, drag to pan&lt;/div&gt;
            &lt;/div&gt;
          &lt;/div&gt;
          &lt;script type="text/javascript"&gt;
  
      var m = [79, 80, 160, 79],
          w = 1280 - m[1] - m[3],
          h = 800 - m[0] - m[2],
          parse = d3.time.format("%Y-%m-%d").parse,
          format = d3.time.format("%Y");
  
      // Scales. Note the inverted domain for the y-scale: bigger is up!
      var x = d3.time.scale().range([0, w]),
          y = d3.scale.linear().range([h, 0]),
          xAxis = d3.svg.axis().scale(x).orient("bottom").tickSize(-h, 0).tickPadding(6),
          yAxis = d3.svg.axis().scale(y).orient("right").tickSize(-w).tickPadding(6);
  
      // An area generator.
      var area = d3.svg.area()
          .interpolate("step-after")
          .x(function(d) { return x(d.date); })
          .y0(y(0))
          .y1(function(d) { return y(d.value); });
  
      // A line generator.
      var line = d3.svg.line()
          .interpolate("step-after")
          .x(function(d) { return x(d.date); })
          .y(function(d) { return y(d.value); });
  
      var svg = d3.select("body").append("svg:svg")
          .attr("width", w + m[1] + m[3])
          .attr("height", h + m[0] + m[2])
        .append("svg:g")
          .attr("transform", "translate(" + m[3] + "," + m[0] + ")");
  
      var gradient = svg.append("svg:defs").append("svg:linearGradient")
          .attr("id", "gradient")
          .attr("x2", "0%")
          .attr("y2", "100%");
  
      gradient.append("svg:stop")
          .attr("offset", "0%")
          .attr("stop-color", "#fff")
          .attr("stop-opacity", .5);
  
      gradient.append("svg:stop")
          .attr("offset", "100%")
          .attr("stop-color", "#999")
          .attr("stop-opacity", 1);
  
      svg.append("svg:clipPath")
          .attr("id", "clip")
        .append("svg:rect")
          .attr("x", x(0))
          .attr("y", y(1))
          .attr("width", x(1) - x(0))
          .attr("height", y(0) - y(1));
  
      svg.append("svg:g")
          .attr("class", "y axis")
          .attr("transform", "translate(" + w + ",0)");
  
      svg.append("svg:path")
          .attr("class", "area")
          .attr("clip-path", "url(#clip)")
          .style("fill", "url(#gradient)");
  
      svg.append("svg:g")
          .attr("class", "x axis")
          .attr("transform", "translate(0," + h + ")");
  
      svg.append("svg:path")
          .attr("class", "line")
          .attr("clip-path", "url(#clip)");
  
      svg.append("svg:rect")
          .attr("class", "pane")
          .attr("width", w)
          .attr("height", h)
          .call(d3.behavior.zoom().on("zoom", zoom));
  
      d3.csv("flights-departed.csv", function(data) {
  
        // Parse dates and numbers.
        data.forEach(function(d) {
          d.date = parse(d.date);
          d.value = +d.value;
        });
  
        // Compute the maximum price.
        x.domain([new Date(1999, 0, 1), new Date(2003, 0, 0)]);
        y.domain([0, d3.max(data, function(d) { return d.value; })]);
  
        // Bind the data to our path elements.
        svg.select("path.area").data([data]);
        svg.select("path.line").data([data]);
  
        draw();
      });
  
      function draw() {
        svg.select("g.x.axis").call(xAxis);
        svg.select("g.y.axis").call(yAxis);
        svg.select("path.area").attr("d", area);
        svg.select("path.line").attr("d", line);
        d3.select("#footer span").text("U.S. Commercial Flights, " + x.domain().map(format).join("-"));
      }
  
      function zoom() {
        d3.event.transform(x); // TODO d3.behavior.zoom should support extents
        draw();
      }
  
          &lt;/script&gt;
        &lt;/body&gt;
      &lt;/html&gt;
  </code></pre>