Я пытаюсь получить график компоновки сил (например, http://bl.ocks.org/mbostock/1748247) в D3, чтобы играть хорошо с реактивным источником данных (meteor.js). Я относительно новичок в обоих этих мирах, и я сталкиваюсь с этой проблемой. У меня правильная компоновка сил и настройка источника данных, так как моя коллекция метеоров отлично работает, но когда я обновляю или добавляю в базу данных с консоли, все узлы летают, как будто только что сгенерированы. Это похоже на то, что все данные рассматриваются как новые, а не только добавление новых данных или переход текущих узлов в соответствие с обновлением.График компоновки диаграмм перерисовывается в D3 при обновлении meteor db
Я пробежал все, что мог, что обсуждал 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;
}
};
}
})
};
};
UPDATE: Это привело к добавлению новых данных. Теперь, я думаю, мне нужно что-то построить, чтобы проверить, были ли изменены какие-либо другие поля.
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);
})
Благодарим за быстрый ответ - это заставило меня двигаться в правильном направлении. Однако мое решение кажется очень неэффективным. Было бы лучше сделать это объектом? Любые идеи о том, как более эффективно определять, есть ли новые объекты, добавленные в массив, или если какая-либо из данных изменилась? –