D3.js 在G元素中选择路径并更改样式

D3.js 在G元素中选择路径并更改样式,d3.js,visualization,D3.js,Visualization,基本上,我试图让所有的路径都变成灰色,除了悬停在上面的路径,而被选中的路径保持原来的颜色。我已经能够将所有其他路径变成灰色,但是我在使用select.this函数和实际访问我想要更改样式的路径时遇到了问题。看起来我实际上已经在g组中找到了path元素,但是我在控制台中遇到了一个错误 Uncaught TypeError: Property 'style' of object #<SVGGElement> is not a function 请,谢谢 D3选择是DOM元素数组的数组。

基本上,我试图让所有的路径都变成灰色,除了悬停在上面的路径,而被选中的路径保持原来的颜色。我已经能够将所有其他路径变成灰色,但是我在使用select.this函数和实际访问我想要更改样式的路径时遇到了问题。看起来我实际上已经在g组中找到了path元素,但是我在控制台中遇到了一个错误

Uncaught TypeError: Property 'style' of object #<SVGGElement> is not a function

请,谢谢

D3选择是DOM元素数组的数组。它们是嵌套数组,因此可以实现嵌套选择,同时为每个子选择保留单独的索引计数和属性

因此,当您运行以下语句时:

var selectedArray = d3.select(this);
所选阵列的结构为[[{SvggeElement}]]。你似乎明白了很多

但是您的selectedArray不仅仅是一个包含单个DOM元素的数组。它也是一个对象,具有选项所具有的所有特殊功能,包括.style函数

但是,在下一行中提取子数组时:

var selectGroup = selectedArray[0];
现在,您只需要一个包含SVG元素节点的普通数组。它没有d3的特殊功能。最后,当您从该数组中提取元素时:

var selectedLine = selectGroup[0];
您只需返回DOM元素节点本身。该对象与您最初选择的对象完全相同。该节点具有.style属性,但没有.style函数

有时,您确实希望从d3选择中提取节点,以便使用作为DOM接口一部分的属性或方法。如果您确实想这样做,上述方法将起作用,或者您可以使用

var svgNode = d3.select("svg")[0][0];
或者,您可以使用selection.node方法,该方法的作用与抓取选择中第一个嵌套中的第一个节点完全相同:

var svgNode = d3.select("svg").node();
但是,如果要在单个DOM元素上使用d3选择方法,可以选择该元素,然后调用该选择上的方法。无论选择包含一个元素还是1000个元素,您的代码都是一样的。如果您的选择完全为空,它甚至不会抛出错误-它只是不会做任何事情!如果要对原始选择的子项使用d3方法,则需要使用selection.select或selection.selectAll子选择方法

顺便说一下,当您使用d3的selection.on方法向元素添加事件处理程序时,d3将自动将该元素的数据对象作为第一个参数传递给事件处理函数。这意味着您可以简化代码以避免二次函数调用:

svg.selectAll("g.team")
 .on("mouseover",function(d){ //d as a function parameter

    var lineName;
    svg.selectAll("path.team.line").style("stroke","#C0C0C0"); 
            //set all to gray

    var selectedLine = d3.select(this);

    selectedLine.style("color", color(d.name) ); 
        //already have the `d` for this element available

    lineName = abbrDict[d.name];

   /* ...etc... */
继续代码:为了定位文本元素,您正在尝试使用元素的.getTotalLength和.getPointAtLength方法。现在,这些方法是DOM接口方法,而不是d3方法,因此您需要实际的{svgpatheElement}节点,而不是d3选择。但是,您目前正在将d3选择与DOM方法混合

要使用纯Javascript从作为其父元素的this元素访问节点,请执行以下操作:

最后,这一行:

this.parentNode.parentNode.appendChild(this.parentNode); 
        //brings team to front, must select the path's g parent 
        //to reorder it
我认为应该是:

this.parentNode.appendChild(this); 
        //brings team to front, must select the path's g parent 
        //to reorder it

因为这已经是元素了。

那么错误来自哪里?请创建一个JSFIDLE演示。我在这里为您创建了一个,但由于我无法访问您的csv数据,因此无法使其正常工作。非常感谢您提供了如此全面和信息丰富的解释。我将尝试这些版本,并感谢您的澄清。然而,在最后一点上,我最初尝试了this.parentNode.appendChildthis,但遇到了困难。不过,我会再试一次!
 var pathNode = this.children[0]; //assuming the <path> is the first child of <g>
 var len = pathNode.getTotalLength();
 var pos = pathNode.getPointAtLength( len );
 var pathNode = selectedLine.node(); //grab the node from the selection
 var len = pathNode.getTotalLength();
 var pos = pathNode.getPointAtLength( len );
this.parentNode.parentNode.appendChild(this.parentNode); 
        //brings team to front, must select the path's g parent 
        //to reorder it
this.parentNode.appendChild(this); 
        //brings team to front, must select the path's g parent 
        //to reorder it