Javascript d3.js树状图:将新旧属性绑定到svg元素
我对d3的理解目前相当有限,我正在处理d3.js的树状图示例。它可以在几个地方找到: 例如,在美国 当我实现它时,一切都很顺利,直到你尝试更新一个属性,比如节点的圆直径。如果我这样做(使用像AngularJS这样的交互式框架来观察参数的变化):节点的大小会发生变化。所以还没问题。但是,如果单击其中一个节点,则大小将重置为初始化大小,而不是新的大小 单击节点时,请执行单击功能:Javascript d3.js树状图:将新旧属性绑定到svg元素,javascript,d3.js,properties,dendrogram,Javascript,D3.js,Properties,Dendrogram,我对d3的理解目前相当有限,我正在处理d3.js的树状图示例。它可以在几个地方找到: 例如,在美国 当我实现它时,一切都很顺利,直到你尝试更新一个属性,比如节点的圆直径。如果我这样做(使用像AngularJS这样的交互式框架来观察参数的变化):节点的大小会发生变化。所以还没问题。但是,如果单击其中一个节点,则大小将重置为初始化大小,而不是新的大小 单击节点时,请执行单击功能: var nodeEnter = node.enter().append("g")
var nodeEnter = node.enter().append("g")
.attr("class", "dendrogramnode2")
.on("click", click);
单击函数调用更新函数
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}
然后更新树状图并打开或关闭必要的节点
function update(source) {
// Compute the new tree layout.
var nodes = tree.nodes(root),
links = tree.links(nodes);
// Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = d.depth * 80; });
// Update the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d) { return d.id || (d.id = ++i); });
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
//.attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })
.on("click", click);
nodeEnter.append("circle")
.attr("r", 1e-6)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
nodeEnter.append("text")
.attr("x", 10)
.attr("dy", ".35em")
.attr("text-anchor", "start")
//.attr("transform", function(d) { return d.x < 180 ? "translate(0)" : "rotate(180)translate(-" + (d.name.length * 8.5) + ")"; })
.text(function(d) { return d.name; })
.style("fill-opacity", 1e-6);
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })
nodeUpdate.select("circle")
.attr("r", 4.5)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
nodeUpdate.select("text")
.style("fill-opacity", 1)
.attr("transform", function(d) { return d.x < 180 ? "translate(0)" : "rotate(180)translate(-" + (d.name.length + 50) + ")"; });
// TODO: appropriate transform
var nodeExit = node.exit().transition()
.duration(duration)
//.attr("transform", function(d) { return "diagonal(" + source.y + "," + source.x + ")"; })
.remove();
nodeExit.select("circle")
.attr("r", 1e-6);
nodeExit.select("text")
.style("fill-opacity", 1e-6);
// Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d) { return d.target.id; });
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {x: source.x0, y: source.y0};
return diagonal({source: o, target: o});
});
// Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", diagonal);
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {x: source.x, y: source.y};
return diagonal({source: o, target: o});
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
函数更新(源代码){
//计算新的树布局。
变量节点=树节点(根),
链接=树。链接(节点);
//为固定深度进行规格化。
forEach(函数(d){d.y=d.depth*80;});
//更新节点…
var node=svg.selectAll(“g.node”)
.data(节点,函数(d){返回d.id | |(d.id=++i)});
//在父节点的上一个位置输入任何新节点。
var nodeEnter=node.enter().append(“g”)
.attr(“类”、“节点”)
//.attr(“转换”,函数(d){return”旋转(“+(d.x-90)+”)平移(“+d.y+”);})
。开启(“点击”,点击);
nodeEnter.append(“圆”)
.attr(“r”,1e-6)
.style(“fill”,函数(d){return d._children?“lightsteelblue”:“fff”});
nodeEnter.append(“文本”)
.attr(“x”,10)
.attr(“dy”,“.35em”)
.attr(“文本锚定”、“开始”)
//.attr(“transform”,函数(d){returnd.x<180?“translate(0)”:“rotate(180)translate”(“+(d.name.length*8.5)+”);)
.text(函数(d){返回d.name;})
.样式(“填充不透明度”,1e-6);
//将节点转换到其新位置。
var nodeUpdate=node.transition()
.持续时间(持续时间)
.attr(“转换”,函数(d){return”旋转(“+(d.x-90)+”)平移(“+d.y+”);})
节点更新。选择(“圆圈”)
.attr(“r”,4.5)
.style(“fill”,函数(d){return d._children?“lightsteelblue”:“fff”});
nodeUpdate.select(“文本”)
.style(“填充不透明度”,1)
.attr(“transform”,函数(d){returnd.x<180?“translate(0)”:“rotate(180)translate”(“+(d.name.length+50)+”);”);
//TODO:适当的转换
var nodeExit=node.exit().transition()
.持续时间(持续时间)
//.attr(“转换”,函数(d){return”对角线(“+source.y+”,“+source.x+”);})
.remove();
nodeExit.select(“圆”)
.attr(“r”,1e-6);
nodeExit.select(“文本”)
.样式(“填充不透明度”,1e-6);
//更新链接…
var link=svg.selectAll(“path.link”)
.data(链接,函数(d){返回d.target.id;});
//在父对象的上一个位置输入任何新链接。
link.enter()插入(“路径”,“g”)
.attr(“类”、“链接”)
.attr(“d”,函数(d){
var o={x:source.x0,y:source.y0};
返回对角线({source:o,target:o});
});
//过渡链接到他们的新位置。
link.transition()
.持续时间(持续时间)
.attr(“d”,对角线);
//将退出节点转换到父节点的新位置。
link.exit().transition()
.持续时间(持续时间)
.attr(“d”,函数(d){
var o={x:source.x,y:source.y};
返回对角线({source:o,target:o});
})
.remove();
//将旧位置隐藏起来,以便过渡。
nodes.forEach(函数(d){
d、 x0=d.x;
d、 y0=d.y;
});
}
因此,此更新函数称为:
我已经为DOM元素设置了一个属性,这些属性在每个数据中没有差异
function dograph(p){
//paramater object is passed and it's name is "p"
d3.select(elementid).selectAll("svg")[0][0]["p"] = p
//at some point update function gets called as part of an event and p is no longer available.
//someSvgElement
.on("mouseover"){update())}
function update(source) {
var p = d3.select(elementid).selectAll("svg")[0][0]["p"];
//stuff happens
}
}
可能不是完美的解决方案,但它对我很有效。将数据的半径部分绑定到圆上更像是D3。这也可以修复这个错误。非常好的评论拉尔斯。但是,在这种情况下,调整一个参数并不需要针对每个数据点进行更改,而是更像一个整体属性:a)在DOM中占用更多空间,B)在更改它时,您需要遍历数据,以便针对每个数据点对其进行更改。所以我认为有一种更有效的方法来处理“开销”属性?我不认为a是重要的,因为它只是一个单一的数字。我也不认为B会是一个问题,因为您可以简单地设置并使用该属性,而不是在您当前的代码中使用数字。如果您在angularjs中的数据上放置$watch,a将变得非常重要。至于B,是的,我就是这么做的,谢谢你的回答:)。