我正在尝试在 D3 中获得一个力布局图(如http://bl.ocks.org/mbostock/1748247),以便与反应性数据源(meteor.js)配合使用。我对这两个世界都比较陌生,我遇到了这个问题。我已经使力布局正常工作,并将数据源设置为我的流星集合效果很好,但是当我从控制台更新或添加到数据库时,所有节点都像刚刚生成一样飞来飞去。就好像所有数据都被视为新数据,而不是仅附加新数据或转换当前节点以匹配更新。
我已经完成了所有关于 D3 和流星的讨论,但是我对这些概念的理解还不够强大,无法进一步了解。感谢任何帮助或正确方向的观点。
我的 d3 区域模板包含在 #constant 中,如下所示:
<template name="ideaspace">
{{#constant}}
<svg>
</svg>
{{/constant}}
</template>
然后在客户端我得到了这个。(请原谅糟糕的代码。我在这里的兔子很远,只是尝试我遇到的一切,看看我是否能得到一些线索)
Template.ideaspace.rendered = function () {
var self = this;
self.node = self.find("svg");
if(! self.handle) {
self.handle = Deps.autorun(function () {
//d3 code
var nodes = DataPoints.find().fetch();
var force = d3.layout.force()
.nodes(nodes)
.size([width, height])
.gravity(.02)
.charge(0)
.on("tick", tick)
;
var svg = d3.select("svg")
.attr("width", width)
.attr("height", '100%')
.attr("id", 'container')
.style("top", '30px')
.style("position", 'fixed')
.attr("pointer-events", "all")
svg.append("rect")
.attr("width", "100%")
.attr("height", "100%")
.attr("fill", "whitesmoke")
.call(d3.behavior.zoom()
.on("zoom", function() {
scale = d3.event.scale;
if (scale<=1){
width = $(window).width()/d3.event.scale;
foci = [{x: '0%', y: 150}, {x: width*1/4, y: 1/2*height}, {x: width*2/4, y: 1/2*height}, {x: width*3/4, y: 1/2*height}];
}
svg.attr("transform", "translate(" + d3.event.translate +
")scale(" + d3.event.scale + ")");
}));
var x =
d3.scale.linear()
.domain([0, width])
.range([0, width]);
var y =
d3.scale.linear()
.domain([0, height])
.range([0, height]);
var bubble = svg.selectAll(".bubble");
bubble = bubble.data(nodes,function (party) { return party._id; });
width = $(window).width();
bubble.enter().append("svg:circle")
.style("fill", function(d) { return color(+d.emperical); })
.style("stroke", "grey")
.attr("id", function(d) { return d.objectId+"_c"; })
.attr("r", function(d) { return d.radius; })
.call(force.drag);
bubble.transition().duration(5000);
force.start();
function tick(e) {
bubble
.each(collide(.5))
.attr("transform", function(d) {return "translate(" + d.x + "," + d.y + ")";
})
}
function cluster(alpha) {
var max = {};
// Find the largest node for each cluster.
nodes.forEach(function(d) {
if (!(d.emperical in max) || (d.radius > max[d.emperical].radius)) {
max[d.emperical] = d;
}
});
return function(d) {
var node = max[d.emperical],
l,
r,
x,
y,
i = -1;
if (node == d) return;
x = d.x - node.x;
y = d.y - node.y;
l = Math.sqrt(x * x + y * y);
r = d.radius + node.radius;
if (l != r) {
l = (l - r) / l * alpha;
d.x -= x *= l;
d.y -= y *= l;
node.x += x;
node.y += y;
}
};
}
})
};
};
更新:这使添加新数据正常工作。现在我想我需要构建一些东西来检查是否有任何其他字段被更改。
self.handle = Deps.autorun(function () {
var topicPoints = TopicPoints.find().fetch();
var found = true;
topicPoints.forEach(function (d) {
if(nodes.length>0){
for(var i = 0; i < nodes.length; i++) {
if (nodes[i]._id == d._id) {
console.log("Found "+ d._id)
found = true;
break;
} else {
found = false
console.log("Not Found "+ d._id)
}
}
if(!found){
nodes.push({
_id:d._id,
title: d.title,
radius: d.radius
});
}
} else {
nodes = topicPoints;
}
});
render(nodes);
})