Ond*_*žka 3 javascript css d3.js
D3有两种设置类的方法:
selection.attr("class", (d) => d.isFoo ? "foo" : "");
selection.classed("foo", (d) => d.isFoo)
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种方法来添加一个按照数据命名的类.就像这样:
selection.classed((d) => "node" + d.id, true);
Run Code Online (Sandbox Code Playgroud)
id因为多个DOM元素将共享该类.attr它,因为它可能会覆盖已存在的其他类.所以我能做到
selection.attr("class", (d) => d3.select(this).attr("class") + " node" + d.id);
Run Code Online (Sandbox Code Playgroud)
感觉有点hackish.
更好的解决方案?或正在进行的功能?
虽然Gerardo的答案是正确的并且有正确的解释,但我认为,弄乱元素类的最简单方法是求助于classList它从Element接口继承的属性.
它
Element.classList是一个只读属性,它返回DOMTokenList元素的类属性的实时集合.
虽然属性本身是只读的,它提供了方法添加,删除和切换类.调用.add()将自动处理先前设置的类,并检查要添加的类是否已分配给元素:
add(String [,String])
添加指定的类值.如果这些类已存在于元素的属性中,则忽略它们.
因此,可以使用selection.each()以下方法添加基于数据的类:
divs.each(function(d) {
this.classList.add("node" + d.name);
});
Run Code Online (Sandbox Code Playgroud)
在.each()方法内this指向实际元素,可用于直接访问classList属性.
var data = [{name: "foo"},
{name: "bar"},
{name: "baz"}];
var body = d3.select("body");
var divs = body.selectAll("myDivs")
.data(data)
.enter()
.append("div")
.attr("class", "someClass");
divs.each(function(d) {
this.classList.add("node" + d.name);
});
//log the classes, you can see the previous class ("someClass") was not overwritten:
divs.each(function() {
console.log(d3.select(this).attr("class"))
})Run Code Online (Sandbox Code Playgroud)
<script src="https://d3js.org/d3.v4.min.js"></script>Run Code Online (Sandbox Code Playgroud)
不幸的是,您无法按照您想要的方式传递函数classed()(即作为第一个参数)。该文档清楚地说明了classed():
选择.classed(名称[, 值])
如果指定了值,则通过设置 class 属性或修改 classList 属性来分配或取消分配所选元素上指定的 CSS 类名称,并返回此选择。指定的名称是一串以空格分隔的类名。(强调我的)
因此,您不能将函数传递给类名。那里的类名必须是固定的。
话虽这么说,您现在正在做什么来添加类名而不覆盖以前存在的类......
selection.attr("class", (d) => d3.select(this).attr("class") + " node" + d.id);
Run Code Online (Sandbox Code Playgroud)
...似乎是 D3 编码人员的标准方式,即使您觉得这是一种 hack。但是,您需要在这里进行一些小修改:不要this与箭头函数一起使用,它不会起作用(检查此示例d3 v4retrieve Drag DOM target from Drag callback when `this` is not available)。因此,这是正确的片段:
selection.attr("class", function (d){
d3.select(this).attr("class") + " node" + d.id);
});
Run Code Online (Sandbox Code Playgroud)
然而,可以按照classed()您想要的方式使用,不是直接使用(同样,您不能将函数传递给它),而是以一种奇怪的解决方法。只是为了向您展示一种使用 执行此操作的方法,出于好奇,我创建了一个比您的解决方案更黑客的classed()演示代码。看看它:
selection.attr("class", (d) => d3.select(this).attr("class") + " node" + d.id);
Run Code Online (Sandbox Code Playgroud)
selection.attr("class", function (d){
d3.select(this).attr("class") + " node" + d.id);
});
Run Code Online (Sandbox Code Playgroud)
正如d.name该函数所提供的each(),第一个参数 ( "node" + d.name) 实际上是一个字符串。