title: D3 Y Axis Scaling and Path Transition
body: <p>I've been very closely following <a href="https://bost.ocks.org/mike/path/" rel="noreferrer">this post</a> about D3 line transitions, implementing something similar to <a href="https://bl.ocks.org/mbostock/1642874" rel="noreferrer">this</a>, except having axis transitions by time.</p>
  
  <p>The end goal is to display real time data points.</p>
  
  <p>I have defined axes, like so:</p>
  
  <pre><code>var x = d3.time.scale()
      .domain([now - (n - 2) * duration, now - duration])
      .range([0, width]);
  
  var y = d3.scale.linear()
      .range([height, 0])
      .domain([0, 100])
  
  var axisx = svg.append('g')
      .attr('class', 'x axis')
      .attr('transform', `translate(0, ${height})`)
      .call(x.axis = d3.svg.axis().scale(x).orient('bottom').tickPadding(10));
  
  var axisy = svg.append('g')
      .attr('class', 'y axis')
      .attr('transform', `translate(${width}, 0)`)
      .call(y.axis = d3.svg.axis().scale(y).orient('right').tickPadding(10));
  </code></pre>
  
  <p>And the line like so:</p>
  
  <pre><code>var line = d3.svg.line()
      .interpolate('basis')
      .x(function(d, i) { return x(now - (n - 1 - i) * duration); })
      .y(function(d, i) { return y(d); });
  </code></pre>
  
  <p>I'm adding a transition function like the linked post talks about to transition the points horizontally over time:</p>
  
  <pre><code>(function tick() {
  
      transition = transition.each(function() {
  
          // Update the domain of the x-axis
          now = new Date();
          x.domain([now - (n - 2) * duration, now - duration]);
  
          // Push the new data point
          data.push(temperature);
  
          // Redraw the line
          svg.select('.line')
              .attr('d', line)
              .attr('transform', null);
  
          // Slide the x-axis left
          axisx.call(x.axis);
  
          // Slide the line left
          path.transition()
              .attr('transform', `translate(${x(now - (n - 1) * duration)})`);
  
          // Pop the old data point off the front
          data.shift();
  
      }).transition().each('start', tick);
  })();
  </code></pre>
  
  <p>So far, things work great when the Y axis domain is fixed. I wanted to dynamically resize the domain and labeling of the Y axis, so I added the following to the transition function:</p>
  
  <pre><code>y.domain([
      Math.min.apply(Math, data) - 10,
      Math.max.apply(Math, data) + 10
  ])
  axisy.call(y.axis);
  </code></pre>
  
  <p>And, while the y axis scale seems to adjust correctly, there's this noticeable glitch effect when the line is redrawn every time the transition function is recalled (not between each transition function tick):</p>
  
  <p><a href="https://postimg.org/image/ewu6d3p6r/" rel="noreferrer"><img src="https://web.archive.org/web/20161010052838/https://s21.postimg.org/gbvr1tq9z/2840154192.gif" alt="Chart Redraw Glitch"></a></p>
  
  <p>Obviously, the problem is that I'm not animating the vertical movement of the line between phases. So, the first question is: is there an easy way in D3 to do this?</p>
  
  <p>I realize that setting the domain based on the max and min of the data presents a challenge because no longer is the data consistently transitioning, it is also scaling.</p>
  
  <p>So I think I'll probably end of having to settle with setting the domain like so:</p>
  
  <pre><code>y.domain([temperature - 10, temperature + 10]);
  </code></pre>
  
  <p>Where the window is fixed. Then I think I will have to alter the transition so that it has attribute:</p>
  
  <pre><code>.attr('transform', `translate(${x(now - (n - 1) * duration)}, ${y(data[1] - data[0]}))`);
  </code></pre>
  
  <p>I can see that this <code>transform</code> will call the associated <code>y</code> function on <code>line</code>, but I'm not sure how I should redefine it. I tried:</p>
  
  <pre><code>.y(function(d, i) { return y(d / i); });
  </code></pre>
  
  <p>But that doesn't seem to work.</p>
  
  <p>How can I get these line transitions working? Thanks so much for your help and I apologize for such an in-depth and lengthy question.</p>
  
  <p><a href="https://gist.githubusercontent.com/jamestaylr/91da56821c0b3d1bd43c58e570698b70/raw/81584752eebc78d6345e80816328cb1d59a0e89c/realtime-d3-graph.js" rel="noreferrer">Link to full gist of code.</a></p>