这是我的css
.node.selectedNode {
width:50px;
height:50px;
stroke-width: 3px;
stroke: #f00;
}
.node.unselectedNode {
width:35px;
height:35px;
stroke-width: 3px;
stroke: #000;
}
我想单击选中的节点(为其选择属性),再次单击并取消选中。 这是一段代码,我检查一个节点的id是否在一个数组中,如果它不是它也添加它,让我能够轻松打印出选定的节点。
if(selectedNodesArray.indexOf(d.coreId)==-1){
selectedNodesArray.push(d.coreId);
d.selectedNode = true; //change style
d.unselectedNode = false;
d3.select(this).classed("selectedNode", true);
console.log("clicked");
}else{
selectedNodesArray.pop(d.coreId);
d.unselectedNode = true;
d.selectedNode = false;
d3.select(this).classed("unselectedNode", true);
console.log("pulled");
}
你可能会注意到我尝试改变风格。现在这工作了两次;当我选择它并取消选择它时。之后它再也不起作用了。有什么想法吗?
此外,我创建了一个按钮,以便清除所有突出显示的节点。就像我在这里,当我点击节点时,它将其属性更改为固定
function dragstart(d) {
d.fixed = true;
d3.select(this).classed("fixed", true);
我想在单击按钮时执行此操作,因此它会更改节点的css属性。我不知道如何挑选出所有的节点,并给它们所有相同的css属性,而不是通过D3并通过这种方式改变.style。
对于这篇冗长的文章,我很抱歉,我希望尽可能多地为您提供详细信息,让每个人都更轻松。
答案 0 :(得分:1)
看起来你做得差不多了。问题是您的代码假定在节点上不调用.classed("selectedNode", true)
会导致它没有应用.selectedNode
类。但实际上(并且您可以在浏览器的“元素”面板中看到此内容),如果您取消选择某个节点,它将会.unselectedNode
,但也会.selectedNode
,因为没有删除.selectedNode
类。并且,任何后续的选择/取消选择都不会再修改内容,因为该节点已经有两个类。
因此,您需要在每次交互发生时删除不适用的类,方法是调用
d3.select(this).classed("selectedNode", false);
和
d3.select(this).classed("unselectedNode", false);
在适当的地方。而那将会奏效。
但现在你有机会重构一些事情。
首先,我的建议是完全忘记unselectedNode
类,只使用类.node
来设置取消选择状态的样式。这样,您只有一个selectedNode
类,它是默认样式的修饰符,并且您的代码将更加简单。
最后,我猜测你正在使用强制布局,所以你已经有了tick()
函数或类似的东西,它每秒都会多次更新所有节点。所以,把它们放在一起,这就是你如何从这个方法中做到的一切:
var selectedNodesArray = [];
function tick() {
var nodes = d3.selectAll('.node').data(force.nodes);
// ENTER
nodes.enter()
.append('circle')// or 'rect' or whatever
.attr('class', 'node')
.on('click', function(d) {
// here you set the selected-ness, but not the visual representation
d.selectedNode = !d.selectedNode; // flip the selected-ness from true->false or vice versa
console.log(d.selectedNode ? "clicked" : "pulled");
// here you manage the array
if(!d.selectedNode) {
// note that pop() is actually unsafe here, bc it
// removes the last-selected node, but what if you
// deselect something from 2 clicks ago?
selectedNodesArray.pop();
}
else {
// Here I recommend pushing d, instead of its d.coreId, because
// then you can use this array to get the actual datums of the
// selectedNodes, rather than just their id
selectedNodesArray.push(d);
}
})
...// do whatever else you need to do to the entering nodes
// UPDATE
nodes
// Here you take care of the representation of selected-ness
.classed('selectedNode', function(d) {
return d.selectedNode
// or: return selectedNodesArray.indexOf(d)==-1
})
// do whatever else you need to do to the updating nodes (position, etc)
}
关于你的第二个问题:我不确定你究竟在那里问什么,但我认为如果你认为你的tick()
方法是基于a更新表示的东西纯数据模型或状态(例如selectedNodesArray
或d.selectedNode
),然后任何交互都可以修改该状态,让tick()
使表示更快。例如,这是取消选择所有内容的大量方法:
// loop through the array and set selected to `false`
selectedNodesArray.forEach(function(d) {
d.selectedNode = false;
})
selectedNodesArray = [];// clear the array
tick();// To update the visuals
最后一件事:在2个地方(selectedNodesArray
和d.selectedNode
)维护有关选定信息的信息有点奇怪。如果您可以选择并使用这两种方式中的一种来表示选择性,那么您将更容易向前发展。