简体   繁体   中英

How to surround all selected SVG path elements with div in d3?

I have pre-created svg picture. My javascript selects elements with certain class and adds html tooltip if I mouseover them. I have group of other elements linked to these hoverable elements by class name. I would like to surround these elements with border (not one by one, but all of them together) if I mouseover.

Do you have any idea how to do this in d3?

My javascript code looks like this (right now I was able to just change the stroke color on hover):

var HTMLmouseTip = d3.select("div.mouse.tooltip");
var tooltip = d3.selectAll(".tooltip:not(.css)"); 
var g = d3.select("svg").select("g"); 

var clusters = g.selectAll(".showTooltip")
            .on("mouseover", function(){
                tooltip.style("opacity", "1");
                heatmap.style("opacity", "1");
                tooltip.style("color", this.getAttribute("fill"));
                var id = this.getAttribute("id");
                HTMLmouseTip
                    .html(this.getAttribute("tooltip"))
                    .style("padding", 5 + "px");
                g.selectAll("."+id)
                    .style("stroke", "red");

            })
            .on("mousemove", function () {
                HTMLmouseTip
                    .style("left", Math.max(0, d3.event.pageX-120) + "px")
                    .style("top", (d3.event.pageY + 20) + "px");
            })
            .on("mouseout", function () {
                return tooltip.style("opacity", "0");
            });

Thanks,

L.

First of you have a problem. This :

var tooltip = d3.selectAll(".tooltip:not(.css)");

Returns an array, so when you do :

 tooltip.style("opacity", "1");

Nothing happens as you have selected the array not the element in the array. So change to :

tooltip.each(function(d){
    d3.select(this).style("opacity", "1").style("color",'red')//
    })

The .each(function(d){... goes through the array and d3.select(this) selects the item in the array.

This now shows your tooltip on mouseover : https://jsfiddle.net/reko91/csLwqzrc/3/

Now to get all your nodes in one <g> element.

Make a container :

var container = d3.select("svg").append("g").attr('id','nodeContainer')

Now select all nodes :

var heatmap = document.getElementsByClassName('NODE_424');

Select the container to append to :

var thisContainer = document.getElementById('nodeContainer');

Go through all nodes and add to container :

for(var i=0;i<heatmap.length;i++){
thisContainer.appendChild(heatmap[i])
}

Now you should be able to just add a border and youre done :)

Updated fiddle : https://jsfiddle.net/reko91/csLwqzrc/5/

For the border, as you can't style <g> elements (they're used to group elements), you have to append a rect to the container and style that instead.

So you have to get the containers x and y to position the rect and width and height for rectangles size. getBBox() is the best way to do this.

var containerBBox =  document.getElementById('nodeContainer').getBBox();

This returns x,y,width,height.

Now append a rect with those attributes and your're done :

 container.append('rect')
  .attr('x', containerBBox.x)
  .attr('y', containerBBox.y)
  .attr('width', containerBBox.width)
  .attr('height', containerBBox.height)
  .style('fill', 'none')
  .style('stroke', 'red')
  .style('stroke-width', 3)

Updated fiddle : https://jsfiddle.net/reko91/csLwqzrc/6/

Now you only want to show the border on mouseover ? And remove on mouseout ?

On mouseover :

 container.style('stroke', 'red')
  .style('stroke-width', 3)

On mouseout :

container.style('stroke', 'none')

Final fiddle : https://jsfiddle.net/reko91/csLwqzrc/11/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM