javascript - d3.js 将节点和标签一起移动

标签 javascript graph svg d3.js

在我们的项目中,我想在单击“添加节点”按钮时动态添加圆圈,并用箭头链接这些圆圈。但是当我链接圆圈的标签时,圆圈的标签不会与圆圈一起移动。代码如下。

JS fiddle 链接:http://jsfiddle.net/pinargocebe/kEhes/3/

如何解决这个问题?

提前致谢..

 <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich" template="layout/template.xhtml">
<ui:define name="body">
    <a4j:commandButton value="Add Node" onclick="mousedown();"> 
   </a4j:commandButton>
    <div id="activationGraphDiv" style="width: 960px; height: 500px">
    </div>
    <rich:popupPanel id="addnode" width="100" height="100">
        <h:form>
            <h:outputLabel value="http://add.mode.deneme#relation" />
            <a4j:commandButton value="OK"
                onclick="#{rich:component('addnode')}.hide()">
</a4j:commandButton>
        </h:form>
    </rich:popupPanel>
    <style type="text/css">
rect {
fill: none;
pointer-events: all;
}

.node {
fill: white;
stroke: pink;
stroke-width: 2;
color: black;
}

.cursor {
fill: none;
pointer-events: none;
}

.link {
stroke: #999;
}

path,line {
stroke: silver;
stroke-width: 2;
fill: none;
}
</style>
    <script src="jquery.pack.js"></script>
    <script type="text/javascript">

var width = 960,
    height = 500;

var sourceNode,targetNode;

var fill = d3.scale.category20();

var force = d3.layout.force()
    .size([width, height])
    .gravity(.05)
.charge(-450)
.linkDistance(200)
    .on("tick", tick);

var svg = d3.select("#activationGraphDiv").append("svg")
.attr("width", width)
.attr("height", height)
.on("mousemove", mousemove);

svg.append("rect")
.attr("width", width)
.attr("height", height);

// Draw Lines
var container = $('#activationGraphDiv');

var line = d3.svg.line()
            .x(function(d) { return d[0]; })
            .y(function(d) { return d[1]; })
            .interpolate('linear');
 svg
.append('svg:path')
.style('stroke-width', 1)
.style('stroke', 'silver')
.style('fill', 'rgba(120, 220, 54, 0.2)');

var lineData = [];

var redrawLine = function() {
var svgLines = svg.selectAll('path.my-lines')
                    .data(lineData)
                    .remove();
svgLines.enter()
        .append('path')
        .attr('d', line(lineData))
        .attr('class', 'my-lines');

svgLines.exit()
        .remove();
};

var mouseIsDown = false;  
container.on('mousemove', function(e) {
    if (mouseIsDown &amp;&amp; sourceNode!=null) {
        lineData[1] = [e.offsetX, e.offsetY];
        redrawLine();    
    }})
    .on('mouseup',function(){
        sourceNode=null;
        targetNode=null;
        mouseIsDown=false;
        svg.selectAll('path.my-lines')
            .data(lineData)
            .remove();
    });


var nodes = force.nodes(),
links = force.links(),
node=svg.selectAll(".node"),
link = svg.selectAll(".link"),
text=svg.selectAll(".nodetext");

var cursor = svg.append("circle")
.attr("r", 0)
.attr("class", "cursor");

restart();

function mousemove() {
    cursor.attr("transform", "translate(" + d3.mouse(this) + ")");
}

var i=0;

function mousedown() {
//x coordinate of node..
var x=document.getElementById("activationGraphDiv").offsetLeft;

//y coordinate of node..
var y=document.getElementById("activationGraphDiv").offsetTop;
var node = {x:x, y: y, name: i},
  n = nodes.push(node);
  i++;
  console.log("node name: "+node.name);
  restart();
  sourceNode=null
  targetNode=null;
  mouseIsDown=false;
}

function tick() {
  link.attr("x1", function(d) { return d.source.x; })
  .attr("y1", function(d) { return d.source.y; })
  .attr("x2", function(d) { return d.target.x; })
  .attr("y2", function(d) { return d.target.y; });

 node.attr("cx", function(d) { return d.x; })
  .attr("cy", function(d) { return d.y; });

 text.attr("x", function(d) {return d.x; })
.attr("y", function(d) { return d.y; });
}
 svg.append("svg:defs").selectAll("marker")
 .data(["arrow"])
 .enter().append("svg:marker")
 .attr("id", String)
 .attr("viewBox", "0 -5 10 10")
 .attr("refX", 10)
 .attr("refY", 0)
 .attr("markerWidth", 10)
 .attr("markerHeight", 10)
 .attr("orient", "auto")
 .append("svg:path")
 .attr("d", "M0,-5L10,0L0,5");

 function restart() {
    node = node.data(nodes);

 node.enter().insert("circle")
  .attr("class", "node")
  .attr("id",function(d){return d.name;})
  .attr("r", 15);

//Insert text to node..
 text=svg.selectAll(".nodetext")
    .data(nodes)
    .enter()
    .append("text")
    .attr("class","nodetext")
    .text(function(d){return d.name;})
    .attr("dx", 13)
    .attr("dy", ".35em");

  d3.selectAll(".node").on("mousedown",function(d){ 
    if(sourceNode==null){
        mouseIsDown = true; 
        lineData[0] = [d3.mouse(this)[0], d3.mouse(this)[1]];
        redrawLine();
        sourceNode=d.index;
        console.log("Source node: "+d.name);
    } 
 })
  .on("mouseup",function(d){ 
    if(targetNode==null &amp;&amp; sourceNode!=null &amp;&amp; mouseIsDown){
        targetNode=d.index;
        links.push({source: sourceNode, target: targetNode});
        lineData[1] = [d3.mouse(this)[0], d3.mouse(this)[1]];
        redrawLine(); 
        console.log("Target node: "+d.name);
        sourceNode=null;
        targetNode=null;
        mouseIsDown = false;
        svg.selectAll('path.my-lines')
            .data(lineData)
            .remove();
        restart();
    }
  });

 link = link.data(links);

 link.enter().insert("line")
      .attr("class", "link");
 link.attr("marker-end", "url(#arrow)");
 force.start();
 }
 </script>
</ui:define>
</ui:composition>

最佳答案

规范的解决方案是将文本和圆圈放入一组。您无需使用 force.tick() 单独移动文本和节点,只需变换组即可。

所以这个:

node.attr("cx", function (d) {
    return d.x;
})
    .attr("cy", function (d) {
    return d.y;
});

text.attr("x", function (d) {
    return d.x;
})
    .attr("y", function (d) {
    return d.y;
});

变成这样:

node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

查看此处的示例:

http://bl.ocks.org/mbostock/950642

关于javascript - d3.js 将节点和标签一起移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17740379/

相关文章:

javascript - 在MySQL数据库表填充的php中对分页表进行排序

javascript - 使用 jQuery Mobile 加载 Google Charts

javascript - 如何减少贝塞尔曲线路径中的点数

javascript - 更改使用 <object> 嵌入的 SVG 的颜色

javascript - 实现任意对象的通用、轻量级且不显眼的标记?

javascript - 根据相邻元素计算行高

algorithm - 我可以在我的图中使用 Dijkstra 的最短路径算法吗?

algorithm - 图论 - 全局最小割及其含义

python - 如何确定递归中的最后一个堆栈空间

jquery - 如何使用CSS3、HTML5、SVG、Jquery制作不规则曲线?