exit()。remove()在节点离开视图时不会删除它

问题描述 投票:1回答:1

我正在使用d3js相对于当前时间从右到左移动圆点。我有几个问题:1。。exit()。remove()不起作用。一旦它退出视图,节点就不会被删除。 2.圆圈的过渡有点跳跃

var circles = g.selectAll('path')
  circles.data(data)
    .enter()
    .append('path')
    .attr("d", symbol.type(d3.symbolCircle))
    .merge(circles)
    .attr("transform", (d) => "translate(" + x(d.x) + "," + y(d.y) + ")");   
  circles.exit().remove();

你可以在这里看到我的完整代码:http://jsfiddle.net/hsdhott/3tdhuLgm/

javascript d3.js
1个回答
0
投票

除了你的enter-exit-update模式不正确之外(请查看下面的代码片段),这里的大问题是数据:

selection.exit()方法不会神奇地选择 - 通常用于以后使用remove() - 基于任何任意标准的元素,例如“离开视图”。它仅基于数据。问题是您的数据永远不会停止增加:

if (count % 10 === 0) {
    var point = {
        x: globalX,
        y: ((Math.random() * 200 + 50) >> 0)
    };
    data.push(point);
}  

因此,在这种情况下,一个非常快速的解决方案是根据您的x域删除数据点:

data = data.filter(function(d) {
    return d.x > globalX - 10000;
});

这只是一个建议,使用您想要的逻辑从数据数组中删除对象。但是,无论使用何种逻辑,都必须将其删除。

关于跳跃过渡,问题是你正在使用selection.transitionsetInterval。那不行,选择了其中之一。

这是您更新的代码:

var data = [];
var width = 500;
var height = 350;
var globalX = new Date().getTime();
/* var globalX = 0; */
var duration = 250;
var step = 10;
var count = 0;
var chart = d3.select('#chart')
  .attr('width', width + 50)
  .attr('height', height + 50);
var x = d3.scaleTime()
  .domain([globalX, (globalX - 10000)])
  .range([0, width]);
var y = d3.scaleLinear()
  .domain([0, 300])
  .range([300, 0]);
// -----------------------------------
// Draw the axis
var xAxis = d3.axisBottom()
  .scale(x)
  .ticks(10)
  .tickFormat(formatter);
var axisX = chart.append('g')
  .attr('class', 'x axis')
  .attr('transform', 'translate(0, 300)')
  .call(xAxis);
// Append the holder for line chart and circles
var g = chart.append('g');

function formatter(time) {
  if ((time.getSeconds() % 5) != 0) {
    return "";
  }
  return d3.timeFormat('%H:%M:%S')(time);
}

function createData() {
  // Generate new data
  var point = {
    x: globalX,
    y: ((Math.random() * 200 + 50) >> 0)
  };
  data.push(point);
}

function callInterval() {
  count++;
  if (count % 3 === 0) createData();
}
// Main loop
function tick() {
  // Generate new data
  if (count % 10 === 0) {
    var point = {
      x: globalX,
      y: ((Math.random() * 200 + 50) >> 0)
    };
    data.push(point);
  }
  data = data.filter(function(d) {
    return d.x > globalX - 10000;
  });
  count++;
  globalX = new Date().getTime();
  var timer = new Date().getTime();
  var symbol = d3.symbol().size([100]),
    color = d3.schemeCategory10;
  var circles = g.selectAll('path')
    .data(data);
  circles = circles.enter()
    .append('path')
    .attr("d", symbol.type(d3.symbolCircle))
    .merge(circles)
    .attr("transform", (d) => "translate(" + x(d.x) + "," + y(d.y) + ")");
  circles.exit().remove();
  // Shift the chart left
  x.domain([timer - 10000, timer]);
  axisX.call(xAxis);
  g.attr('transform', null)
    .attr('transform', 'translate(' + x(globalX - 10000) + ')');
  // Remote old data (max 50 points)
  if (data.length && (data[data.length - 1].x < (globalX - 10000))) data.shift();
}
tick();
setInterval(tick, 10);
.axis {
  font-family: sans-serif;
  font-size: 12px;
}

.line {
  fill: none;
  stroke: #f1c40f;
  stroke-width: 3px;
}

.circle {
  stroke: #e74c3c;
  stroke-width: 3px;
  fill: #FFF;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg id="chart"></svg>
© www.soinside.com 2019 - 2024. All rights reserved.