javascript - D3.js(v4) 力导向图布局 一定要用tick() 方法么才能得到正确地数据坐标点么?
黄舟
黄舟 2017-04-11 13:33:07
0
1
824

Demo
http://codepen.io/jingxiao/pe...

var nodes = [ { name: "BeiJing" }, { name: "XiaMen" }, { name: "XiAn" }, { name: "HangZhou" }, { name: "ShangHai" }, { name: "QingDao" }, { name: "NanJing" } ]; var links = [ { source : 0 , target: 1 } , { source : 0 , target: 2 } , { source : 0 , target: 3 } , { source : 1 , target: 4 } , { source : 1 , target: 5 } , { source : 1 , target: 6 } ]; var width = 800; var height = 600; var svg = d3.select("body") .append("svg") .attr("width",width) .attr("height",height); // 通过布局来转换数据,然后进行绘制 var simulation = d3.forceSimulation(nodes) .force("link", d3.forceLink(links).distance(100)) .force("charge",d3.forceManyBody()) .force("center",d3.forceCenter(width/2, height/2)); var color = d3.scaleOrdinal(d3.schemeCategory20); // 绘制 var svg_links = svg.selectAll("line") .data(links) .enter() .append("line") .style("stroke","#ccc") .style("stroke-width",3); var svg_nodes = svg.selectAll("circle") .data(nodes) .enter() .append("circle") .attr("r",10) .style("fill",function(d,i){ return color(i); }) .attr("cx",function(d){return d.x;}) .attr("cy",function(d){return d.y;}); var svg_text = svg.selectAll("text") .data(nodes) .enter() .append("text") .style("fill","#000") .attr("dx",20) .attr("dy",10) .text(function(d){return d.name;}); console.log("转换后的nodes links数据:"); console.log(nodes); console.log(links); function draw(){ svg_nodes .attr("cx",function(d){console.log(d);return d.x;}) .attr("cy",function(d){return d.y;}); svg_text .attr("x", function(d){ return d.x; }) .attr("y", function(d){ return d.y; }); svg_links .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; }); } simulation.on("tick",draw); //draw();

通过力导向图来转换节点nodes和线路links为可绘制的数据,然后去绘制连线图。有个疑问是tick()方法。

上述代码中为什么我不能在得到nodes links数据后,直接调用draw() 绘制呢,这个时候的数据有问题,用tick正常,为什么?
类似问题
Why do we need force.on('tick'.. in d3

在console地方 感觉已经得到正确的节点线路坐标数据,

然后就可以直接绘制调用draw() 方法把对应的坐标数据绑定到元素上这样应该就ok了,但事实上在demo中注释tick方法调用,直接draw() 得到的结果是这样

都跑到左上角去了,事实上此时的坐标点位置并不是刚刚console.log()输出的那些数据。
我在draw()方法中输出了数据

比如Beijingz这个点的 坐标位置(0,0),下面节点显示的位置也和之前不对。但我把输出的object展开看数据又是对的。

有点懵逼,这是怎么回事呢?

tick()方法的作用,我的理解是没到一个时刻都要调用里面的方法更新节点坐标位置。
但我只想初始化数据得到可绘制的数据,然后初始化显示,后面的节点拖拽更新自己写方法来做,只是想用力导向图来转换第一次的数据。

黄舟
黄舟

人生最曼妙的风景,竟是内心的淡定与从容!

reply all (1)
大家讲道理

自问自答
有一点要清楚就是力导向图布局的形成是一个异步的过程而且需要一定时间几秒钟
所以当draw() 去执行的时候,力导向图布局并没有完成,所以取到各节点的坐标是很小的偏移量,如上图三。所以绘制的图形都在左上角去了。
验证这一点,加个setTimeout就行了

setTimeout(draw,5000);

你会发现几秒后布局不好了,数据就正常了绘制出来的图形就OK了,但为什么console.log()打印出来的数据展开会变是什么原因呢,调试工具的问题,好奇怪。

    Latest Downloads
    More>
    Web Effects
    Website Source Code
    Website Materials
    Front End Template
    About us Disclaimer Sitemap
    php.cn:Public welfare online PHP training,Help PHP learners grow quickly!