选择G元素中的路径并更改样式

Eri*_*rie 5 visualization d3.js

基本上我试图让所有的路径除了一个被翻转为灰色的路径,而被选中的路径保持它的原始颜色.我已经能够将所有其他路径变为灰色,但是我遇到了"select.this"功能的问题并且实际上访问了我想要改变样式的路径.看来我实际上已经设法进入g组中的path元素,但是我在控制台中遇到错误

Uncaught TypeError: Property 'style' of object #<SVGGElement> is not a function
Run Code Online (Sandbox Code Playgroud)

相关代码:

    svg.selectAll("g.team")
    .on("mouseover",function(){
            console.log("I see you!");
            var lineName;
            var accuracy = 10;

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

            var selectedArray = d3.select(this);
            console.log(selectedArray);

            var selectGroup = selectedArray[0];
            console.log("should be group:"+selectGroup);

            var selectedLine = selectGroup[0];;

            selectedLine.style("color",function(d){  //let active keep color
            lineName = abbrDict[d.name];  //full name to be at end of line
            return color(d.name);
        });

            //get position of end of line
        var len = d3.select(this).children().node().getTotalLength();
        var pos = d3.select(this).node().getPointAtLength(len);  
        //append text to end of line
        svg.append("text")
            .attr("id","tooltip")
            .attr("x",pos.x-55)
            .attr("y",pos.y)
            .text(lineName)
            .style("font-family","sans-serif")
            .style("font-size",13);

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

    })
    .on("mouseout",function(){
            d3.select("#tooltip").remove();

            d3.selectAll("team").selectAll("path")
              .transition()
              .style("stroke",function(d){
                  return color(d.name);  //return all the colors
               });

            d3.selectAll("axis").selectAll("line").style("color","black");

    });
Run Code Online (Sandbox Code Playgroud)

谢谢,麻烦您了!

Ame*_*aBR 21

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

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

var selectedArray = d3.select(this);
Run Code Online (Sandbox Code Playgroud)

selectedArray是结构[[ {SVGGElement} ]].你似乎很明白.

selectedArray是不是只是含含一个DOM元素的数组的数组.它也是一个d3.selection对象,具有选择所具有的所有特殊功能,包括.style()功能.

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

var selectGroup = selectedArray[0];
Run Code Online (Sandbox Code Playgroud)

您现在只有一个包含SVG <g>元素节点的普通数组.它没有d3的特殊功能.最后,当您从该数组中提取元素时:

var selectedLine = selectGroup[0];
Run Code Online (Sandbox Code Playgroud)

您只需返回DOM元素节点本身.这this您最初选择的对象完全相同.该节点有一个.style属性,但不是一个.style()函数.

有时,您确实希望从d3选择中提取节点,以便使用属于DOM接口的属性或方法.如果你确实想这样做,上面的方法就可以了,或者你可以用一行来访问它

var svgNode = d3.select("svg")[0][0];
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用selection.node()完全相同的方法(抓取选择中第一个嵌套中的第一个节点):

var svgNode = d3.select("svg").node();
Run Code Online (Sandbox Code Playgroud)

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

svg.selectAll("g.team")
 .on("mouseover",function(){

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

    var selectedGroup = d3.select(this);
    var selectedLine = selectedGroup.select("path.team.line");
                       //this only selects the (first) path that is a child
                       //of the selected group

    selectedLine.style("color",function(d){  //let active keep color
        lineName = abbrDict[d.name];  //full name to be at end of line
        return color(d.name);
    });

   /* ...etc... */
Run Code Online (Sandbox Code Playgroud)

顺便说一句,当您使用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... */
Run Code Online (Sandbox Code Playgroud)

继续使用代码:为了定位文本元素,您尝试使用元素的方法.getTotalLength().getPointAtLength()方法<path>.现在,这些方法都是DOM接口方法,而不是d3方法,所以需要实际{SVGPathElement}节点,而不是d3选择.但是,您现在将d3选择与DOM方法混合在一起.

要使用this元素中的纯Javascript (它是父<g>元素)访问节点:

 var pathNode = this.children[0]; //assuming the <path> is the first child of <g>
 var len = pathNode.getTotalLength();
 var pos = pathNode.getPointAtLength( len );
Run Code Online (Sandbox Code Playgroud)

或者,您可以<path>从上面创建的d3选项中访问元素:

 var pathNode = selectedLine.node(); //grab the node from the selection
 var len = pathNode.getTotalLength();
 var pos = pathNode.getPointAtLength( len );
Run Code Online (Sandbox Code Playgroud)

最后,这一行:

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

我认为应该只是:

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

(因为已经this<g>元素).