quape
quape

Reputation: 746

darken rect/circle on mouseover in d3

I'm using d3 to draw several rectangles and circles that are filled wich certain colors.

Now, my objects shall be darkened when hovering the mouse pointer over them. My idea was to use CSS by putting a black background with alpha on the g tag that surrounds each object:

g:hover {
  background-color: rgba(0, 0, 0, .5);
}

But that doesn't work. It does work when I put a opacity: .5 there, but I want it darker, not lighter. Does anyone have some hint? Thank you!

Upvotes: 2

Views: 9410

Answers (4)

atlas_scoffed
atlas_scoffed

Reputation: 4127

With modern browsers you can use CSS brightness function to lighten/darken a color.

.on('mouseover', (event, d) => {
    d3.select(event.target)
       .style('filter', 'brightness(50%)')
    })

Upvotes: 2

Alexander
Alexander

Reputation: 225

For D3 vers. 4 On my donut chart i faced the same problem. I found mboostocks solution which can be found here. I took his second example and replaced "brighter" with "darker". My resulting code:

.on("mouseover", function(d){
    d3.select(this).style("fill", function() {
        return d3.rgb(d3.select(this).style("fill")).darker(0.2);
    });
});

Upvotes: 2

quape
quape

Reputation: 746

The :hover thing worked in general but it was the wrong approach to apply it on the g tag which is a parent of the rectangle, not an overlaying child.

I now solved the whole problem by adding a mouseover event to the rect tag, reading out the color value of the fill attribute and calculated a darker value out if it. Possibly not the finest solution but I have no other idea and it works.

.on("mouseover", function() {
    if((r = $(this).css("fill").match(/(\d+),\s*(\d+),\s*(\d+)/i))) {
        for(var i = 1; i < 4; i++) {
            r[i] = Math.round(r[i] * .5);
        }
        $(this).attr("fill-old", $(this).css("fill"));
        $(this).css("fill", 'rgb('+r[1]+','+r[2]+','+r[3]+')');
    }
})
.on("mouseout", function() {
    if($(this).attr("fill-old")) $(this).css("fill", $(this).attr("fill-old"));
});

Upvotes: 3

Samih
Samih

Reputation: 1088

I don't think you can reliably use the hover pseudo on SVG elements. Instead use d3 to add a class on mouseover and remove it on mouseout.

For example:

svg.append("g")
    .on("mouseover", function() {
        d3.select(this).classed("hover", true);
      })
    .on("mouseout", function() {
         d3.select(this).classed("hover", false);
    })

then in CSS

g.hover {
    background-color: rgba(0, 0, 0, .5);
}

Hope that helps.

EDIT: Maybe you can use :hover. See this question and answer https://stackoverflow.com/a/9210392/2594702 .

Basically it says use fill: rgba(0, 0, 0, .5) instead of background-color.

I'm sure I remember reading when I was learning D3 to use mouseover and mouseout. Maybe browser support wasn't as good then as it is now.

Upvotes: 5

Related Questions