在d3.js图形上附加一条额外的线会导致抖动

时间:2014-10-17 09:10:28

标签: javascript d3.js

这是path transitions的例子。唯一的问题是,当我添加第二行时,黑线似乎平滑移动,但灰线以非常抖动的方式移动。

更令人惊讶的是,即使我在评论这一行path2.transition().duration(duration).ease("linear").attr("transform", "translate(" + x(now - (n - 1) * duration) + ")");时,两条线都在继续移动。为什么会这样?

当添加更多行时,有没有办法让图表顺利移动?
以下代码可以放在任何空的' .html'文件,它将工作。

代码:

<head>
<style>
svg {
  font: 10px sans-serif;
}

.line1 {
  fill: none;
  stroke: #000;
  stroke-width: 1.5px;
}
.line2 {
  fill: none;
  stroke: #999;
  stroke-width: 1.5px;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  opacity: 0.5;
  shape-rendering: crispEdges;
}


</style>    
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body>
   <div id='placeholder' style='width: 580px; height: 380px;'></div>
<script type="text/javascript">
var outData=0, inData=0;

(
function() 
{
var n = 40;
var random = d3.random.normal(0, .2), data = d3.range(n).map(random), data2 = d3.range(n).map(random);
var n = 243,
    duration = 200,
    now = new Date(Date.now() - duration),
    count = 0,
    data = d3.range(n).map(function() { return 0; }),
    data2 = d3.range(n).map(function() { return 0; });

var margin = {top: 20, right: 0, bottom: 20, left: 40},
    width = 580 - margin.right,
    height = 400 - margin.top - margin.bottom;

var x = d3.time.scale().domain([now - (n - 2) * duration, now - duration]).range([0, width]);
var y = d3.scale.linear().domain([-1, 1]).range([height, 0]);

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); });

var line2 = d3.svg.line()
    .interpolate("basis")
    .x(function(d, i) { return x(now - (n - 1 - i) * duration); })
    .y(function(d, i) { return y(d); });

var svg = d3.select("body").select("#placeholder").append("p").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .style("margin-left", -margin.left + "px")
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

svg.append("defs").append("clipPath")
    .attr("id", "clip")
  .append("rect")
    .attr("width", width)
    .attr("height", height);

var axis = svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(x.axis = d3.svg.axis().scale(x).orient("bottom"));

var yaxis = svg.append("g")
    .attr("class", "y axis")
    .call(y.axis = d3.svg.axis().scale(y).orient("left"));

var path = svg.append("g")
    .attr("clip-path", "url(#clip)")
  .append("path")
    .data([data])
    .attr("class", "line1");

var path2 = svg.append("g")
    .attr("clip-path", "url(#clip)")
  .append("path")
    .data([data2])
    .attr("class", "line2");    

//----------------------- legend

   svg.append("svg:rect").attr("x", 15).attr("y", -10).attr("width", 5).attr("height", 5).attr("fill", "#000");
   svg.append("svg:text").attr("x", 35).attr("y", -5).attr("text-anchor", "right").text("A");
   svg.append("svg:rect").attr("x", 80).attr("y", -10).attr("width", 5).attr("height", 5).attr("fill", "#999");
   svg.append("svg:text").attr("x", 90).attr("y", -5).attr("text-anchor", "right").text("B");

tick();

d3.select(window).on("scroll", function() { ++count; });

function tick() 
{
  // push the accumulated count onto the back, and reset the count
  var newRandData = random();
  var newRandData2 = random();
  data.push(newRandData);
  data2.push(newRandData2);

  // update the domains
  now = new Date();
  x.domain([now - (n - 2) * duration, now - duration]);
  //get the min and max of data and data2 to set the y domain
  var minmax = []; 
  minmax.push(d3.min(data)); minmax.push(d3.max(data));
  minmax.push(d3.min(data2)); minmax.push(d3.max(data2));
  y.domain([d3.min(minmax), d3.max(minmax)]);
  y = d3.scale.linear().domain([d3.min(minmax), d3.max(minmax)]).range([height, 0]);
  yaxis.call(y.axis = d3.svg.axis().scale(y).orient("left"));

  count = 0;
  // redraw the lines
  svg.select(".line1").attr("d", line).attr("transform", null);
  svg.select(".line2").attr("d", line2).attr("transform", null);

  // slide the x-axis left
  axis.transition().duration(duration).ease("linear").call(x.axis);

  // slide the line left
  path.transition().duration(duration).ease("linear").attr("transform", "translate(" + x(now - (n - 1) * duration) + ")").each("end", tick);
  // slide the line left
  path2.transition().duration(duration).ease("linear").attr("transform", "translate(" + x(now - (n - 1) * duration) + ")");

  // pop the old data point off the front
  data.shift();
  data2.shift();
}

})();

</script>
</body>

更新

我现在保留了两个滴答功能。抖动似乎是x缩放的问题。当我使用时间刻度时,它会抖动(现在也会闪烁)。当我使用线性刻度时,它是平滑的 var x = d3.time.scale().domain([now - (n - 2) * duration, now - duration]).range([0, width]);似乎是问题,但我不明白为什么。

<head>
<style>
svg {
  font: 10px sans-serif;
}

.line1 {
  fill: none;
  stroke: #000;
  stroke-width: 1.5px;
}
.line2 {
  fill: none;
  stroke: #999;
  stroke-width: 1.5px;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  opacity: 0.5;
  shape-rendering: crispEdges;
}


</style>    
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body>
   <div id='placeholder' style='width: 580px; height: 380px;'></div>
<script type="text/javascript">
var outData=0, inData=0;
var newRandData, newRandData2;

//(function() {
var n = 10;
var random = d3.random.normal(0, .2), data = d3.range(n).map(random), data2 = d3.range(n).map(random);
var n = 243, duration = 500,
    now = new Date(Date.now() - duration),
    count = 0,
    data = d3.range(n).map(function() { return 0; }),
    data2 = d3.range(n).map(function() { return 0; });

var margin = {top: 20, right: 0, bottom: 20, left: 40},
    width = 580 - margin.right,
    height = 400 - margin.top - margin.bottom;

//var x = d3.time.scale().domain([now - (n - 2) * duration, now - duration]).range([0, width]);
var x = d3.scale.linear().domain([0, n - 1]).range([0, width]);//x axis scale
var y = d3.scale.linear().domain([-1, 1]).range([height, 0]);

//var line1 = d3.svg.line()./*interpolate("basis").*/x(function(d, i) { return x(now - (n - 1 - i) * duration); }).y(function(d, i) { return y(d); });
//var line2 = d3.svg.line()./*interpolate("basis").*/x(function(d, i) { return x(now - (n - 1 - i) * duration); }).y(function(d, i) { return y(d); });
var line1 = d3.svg.line().interpolate("basis").x(function(d, i) { return x(i); }).y(function(d, i) { return y(d); });
var line2 = d3.svg.line().interpolate("basis").x(function(d, i) { return x(i); }).y(function(d, i) { return y(d); });

var svg = d3.select("body").select("#placeholder").append("p").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .style("margin-left", -margin.left + "px")
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

svg.append("defs").append("clipPath")
    .attr("id", "clip")
  .append("rect")
    .attr("width", width)
    .attr("height", height);

var axis = svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(x.axis = d3.svg.axis().scale(x).orient("bottom"));

var yaxis = svg.append("g")
    .attr("class", "y axis")
    .call(y.axis = d3.svg.axis().scale(y).orient("left"));

var path = svg.append("g")
    .attr("clip-path", "url(#clip)")
  .append("path")
    .data([data])
    .attr("class", "line1")
    .attr("d", line1);

var path2 = svg.append("g")
    .attr("clip-path", "url(#clip)")
  .append("path")
    .data([data2])
    .attr("class", "line2")
    .attr("d", line2);

ticktick();
ticktick2();

function ticktick() 
{
  // push a new data point onto the back
  data.push(random());

  // redraw the line, and slide it to the left
  path
      .attr("d", line1)
      .attr("transform", null)
    .transition()
      .duration(duration)
      .ease("linear")
      .attr("transform", "translate(" + x(-1) + ",0)")
      .each("end", ticktick);

  // pop the old data point off the front
  data.shift();
}
function ticktick2() 
{
  // push a new data point onto the back
  data2.push(random());

  // redraw the line, and slide it to the left
  path2
      .attr("d", line2)
      .attr("transform", null)
    .transition()
      .duration(duration)
      .ease("linear")
      .attr("transform", "translate(" + x(-1) + ",0)")
      .each("end", ticktick2);

  // pop the old data point off the front
  data2.shift();
}

</script>
</body>

0 个答案:

没有答案