在带有D3J的路径中间添加顶点



如何根据用户操作修改路径?例如:我有一个由三个点A,B和C组成的路径。当用户在路径上单击路径(现有点以外的其他地方)时,我想在路径上添加一个新点。如何在正确位置将新点插入路径?

在这里您可以找到一个示例

var nodes = [[30, 130], [250, 250], [400,130]];
var line = d3.svg.line();
var svg = d3.select("body").append("svg")
        .attr("width", 500)
        .attr("height", 5000);
var path = svg.append("path")
            .datum(nodes)
            .attr("class", "line")
            .call(update);
path.on("click", insertNode);
function update() {
  svg.select("path").attr("d", line);
  var circle = svg.selectAll("circle")
      .data(nodes, function(d) { return d; });
}
function insertNode(data) {
     //create the new node:
   var newNode = [];

   var newNode = d3.mouse(svg.node());
       //find coordinates relative to the plotting region
   nodes.push(newNode); //add to your nodes array

   update();
}

如果单击第一个段(sx-> dx),从新节点的路径末端添加了新段,因为我在节点数组末尾添加了新节点。正确的行为是一个路径中的新节点(节点数组)[30,130]和[250,250]

谢谢!以前!

您不能简单地将新节点添加到数组中,必须先确定其位置。这样做的一种方法是计算与所有点的角度。当绝对值相同时,您就会知道自己找到了插入位置。唯一的障碍是,由于行的宽度,它不会完全是180度,因此您必须考虑到这一点。以下代码尝试了一下并将新节点拼接到数组中。

var idx = 0, prevAngle;
nodes.forEach(function(n, i) {
    var angle = Math.abs(Math.atan((n[1] - newNode[1]) / (n[0] - newNode[0])));
    if(Math.abs(angle - prevAngle) < 0.05) {
        idx = i;
    }
    prevAngle = angle;
});
tmp = nodes.slice(0, idx);
tmp.push(newNode);
nodes = tmp.concat(nodes.slice(idx));

在此处完成示例。

链接的数据对象包含源和目标节点数据对象,因此您可以使用该信息将链接分为二,通过新节点连接。

示例代码,假设linkElements是您的D3选择链接<path><line>元素,而linksnodes是与force.links()force.nodes()相对应的数据阵列:

linkElements.on("click", insertNode);
function insertNode(linkData){ //parameter is the *link's* data object
   //create the new node:
   var newNode = {};
   var clickPoint = d3.mouse(this.parentNode);
       //find coordinates relative to the plotting region
   newNode.x = xScale.invert(clickPoint[0]);
   newNode.y = yScale.invert(clickPoint[1]);
       //convert coordinates to data values
   nodes.push(newNode); //add to your nodes array

   //create a new link for the second half of the old link:
   var newLink = {source:newNode, target:linkData.target};
   links.push(newLink); //add to your links array
   //update the old link to point to the new node:
   linkData.target = newNode;
   update();
}

当然,这仅更新节点和链接的数据对象,您的update()函数将必须更新力布局并创建输入SVG元素。

最新更新