用新的路径转换替换d3.js路径转换?

时间:2014-12-15 09:47:05

标签: svg d3.js

我看过this个问题和many other个例子,但它没有帮助。我在this page上尝试了最后一个例子,在5秒之后,我想要绘制的曲线路径完全消失,再过5秒钟,我想要创建一条新路径。

我已经尝试了以下代码,但是虽然删除了整个svg元素本身,但当我使用appendGraph()再次创建svg和路径时,同样的旧路径重新出现。如何确保完全删除旧路径,并且在删除图形时也不会调用tick函数?

小提琴在这里:http://jsfiddle.net/nav9/5uygqj9v/

代码是:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

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

.noselect {
/* these are to disable text selection */
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

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

rect.zoom {
stroke: steelblue;
fill-opacity: 0.3;
}

#placeholder {margin: 10px 5px 15px 70px;}

</style>

<script type="text/javascript" src="http://d3js.org/d3.v3.js"></script>

</head>
<body>
<div id="placeholder" ></div>
<script>
//---------globals
var timer = null, interval = 500, value = 0;
var value1 = 0;
var n = 143, duration = interval, now = new Date(Date.now() - duration), count = 0, data = d3.range(n).map(function() { return 0; });

var margin = {top: 20, right: 40, bottom: 50, left: 60}, width = 580 - margin.right, height = 420 - 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 svg, path, yaxis, axis;



//--------program starts
appendGraph();
tick();
value1 = 0;
setTimeout(function() {removeGraph();}, 5000);
setTimeout(function() {addGraphAgain();}, 10000);



//-------------------------------functions -------------------------------
function appendGraph()
{
  svg = d3.select("body").select("#placeholder").append("p").append("svg:svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .attr("id", "mainSVG")
    .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);

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

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

path = svg.append("g")
    .attr("clip-path", "url(#clip)")
  .append("path")
    .data([data])
    .attr("id", "line1")
    .attr("fill", "none")
    .attr("stroke", "black")
    .attr("stroke-width", "1.5px")
    .style("visibility","visible");

}//appendGraph

//TODO: These tick functions could be simplified to handle more lines on the graph
function tick() 
{
  // push the accumulated count onto the back, and reset the count
  value1 = Math.random() * 100;
  if (value1 >= 0) {data.push(value1);} else {data.push(0);}//ensure that no NaN or undefined values corrupt the range

  // update the domains
  now = new Date();
  x.domain([now - (n - 2) * duration, now - duration]);

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

  // slide the line left
  path.transition().duration(duration).ease("linear").attr("transform", "translate(" + x(now - (n - 1) * duration) + ")").each("end", tick);
  y.domain([0, 100]);
  y = d3.scale.linear().domain([0, 100]).range([height, 0]);      
  yaxis.call(y.axis = d3.svg.axis().scale(y).orient("left"));  

  // pop the old data point off the front
  data.shift();
  console.log("tick being called");
}

function removeGraph()
{
    path.transition().duration(0).each(function() { this.__transition__.active = 0; });//at least this is stopping tick from being called   
    svg.selectAll("*").remove();
    //-------tried these too
//  d3.select("#mainSVG").remove("svg");
//  d3.select("#line1").remove("path");
//  path.remove();
    //d3.selectAll("path").attr("d", "Z");
    console.log("REMOVED");
}//removeGraph

function addGraphAgain()
{
    appendGraph();

    tick();

    value1 = 0; 
    console.log("ADDED AGAIN");
}//addGraphAgain
</script>
</body>
</html>

1 个答案:

答案 0 :(得分:0)

这个问题不是一个确切的答案,但是因为我之所以问这个原因是因为我希望有一些阶段,我想将空输入发送到图表,除了删除该行之外似乎没有别的方法可以做到这一点并用新线替换它。

在d3.js中处理null或NaN数据或丢失数据或暂时不显示数据的技巧是使用defined

它的一个工作示例here,在线转换中,它是这样的:
我在if (counter%5==0) ran = null;data.push(ran);处提供一个随机数,.defined(function(d) { return d != null; })通过不在那里画线来处理空值。

<!DOCTYPE html>
<meta charset="utf-8">
<style>

svg {
  font: 10px sans-serif;
}

.line {
  fill: none;
  stroke: #000;
  stroke-width: 1.5px;
}

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

</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>

var n = 40,
    random = d3.random.normal(0, .2),
    data = d3.range(n).map(random);

var margin = {top: 20, right: 20, bottom: 20, left: 40},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var x = d3.scale.linear()
    .domain([0, n - 1])
    .range([0, width]);

var y = d3.scale.linear()
    .domain([-1, 1])
    .range([height, 0]);

var line = d3.svg.line()
    .defined(function(d) { return d != null; })
    .x(function(d, i) { return x(i); })
    .y(function(d, i) { return y(d); });

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .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);

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

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

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

var counter = 0;    
tick();

function tick() 
{
  // push a new data point onto the back
  var ran = random();
  counter++;
  if (counter%5==0) ran = null;
  data.push(ran);

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

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

</script>
相关问题