Emilie Picard-Cantin
Emilie Picard-Cantin

Reputation: 290

How to use mix-blend-mode with d3 stroke?

I have a packed circles graph (see this jsfiddle) where the circles have a black stroke on hover. What I would like is to use the CSS property mix-blend-mode: multiply to change the circle border on hover.

Here is an example of what I want when the circle is selected or when we hover over the circle. The stroke is a darker shade of the fill color. I do not want to define each stroke color individually, because they are dynamically generated.

enter image description here

Can I use this CSS property combined with d3.js circles so that only the stroke has the mix-blend-mode property ? Note that I'm using version 4 of d3.js (d3.v4.min.js).

Upvotes: 0

Views: 1062

Answers (2)

JamesDK
JamesDK

Reputation: 96

bit late here. was looking for nearly the same problem (to use mix-blend-mode only for the stroke, not the fill, but this doesnt work this way). anyway, saw your prob.. i'm not into d3.js, but maybe this helps after 2years:

you define the fill colors in your js (they are not dynamically), so best way is, to define there also the stroke colors.

in your js, i added a second color array 'my_colors_stroke' and placed beneath after the fill style a stroke style. also set in your css the default stroke-width to 0.

this here is a quick n dirty solution, but would recommend you to look at d3.js bubble docs because they have a slightly different approach to build bubbles, which looks easier.

var data = {
  "name": "Main",
  "children": [{
      "id": "0",
      "group": 0,
      "name": "Group0",
      "children": [{
        "id": "0_0",
        "name": "Subgroup_0_0",
        "subgroup": 0,
        "group": 0,
        "children": [{
            "node": 0,
            "id": "0_0_0",
            "stk_id": 247,
            "stk_names": ["Person1"],
            "name": "Person1",
            "size": 0.5
          },
          {
            "node": 1,
            "id": "0_0_1",
            "stk_id": 3309,
            "stk_names": ["Person2"],
            "name": "Person2",
            "size": 0.5
          }
        ]
      }]
    },
    {
      "id": "1",
      "group": 1,
      "name": "Group1",
      "children": [{
        "id": "1_1",
        "name": "Subgroup_1_1",
        "subgroup": 1,
        "group": 1,
        "children": [{
            "node": 0,
            "id": "1_1_0",
            "stk_id": 285,
            "stk_names": ["Person3"],
            "name": "Person3",
            "size": 0.5
          }
        ]
      }]
    }
  ]
}

var my_colors = ["#FFD753", "#FF9D51"];
var my_colors_stroke = ["#efc743", "#ef8d41"];

var size = 500;
console.log("Variables set");

var svg = d3.select(".circles").append("svg")
  .attr("class", "circle_packed")
  .attr("id", "circle_packed")
  .attr("width", size)
  .attr("height", size);
console.log("Initialized svg");

var g = svg.append("g");
var pack = d3.pack().size([size , size ]).padding(5);

var root = d3.hierarchy(data)
  .sum(function(d) { return d.size; })
  .sort(function(a, b) { return b.value - a.value; });
console.log("Initialized pack");
  
var nodes = pack(root).descendants();
console.log(nodes);

var circle = g.selectAll("circle")
  .data(nodes)
  .enter().append("circle")
  .attr("class", function(d) {return d.parent ? (d.children ? "node " : "node node--leaf ") : "root "; })
  .attr("id", function(d) {return "node_"+d.data.id;})
  .attr("r", function(d) { return d.r; })
  .style("fill", function(d) {
    if(d.depth==2){
      return my_colors[d.data.group];
    } else {
      return null;
    }
  })
  .style("stroke", function(d) {
    if(d.depth==2){
      return my_colors_stroke[d.data.group];
    } else {
      return null;
    }
  });
        
var text = g.selectAll("text")
  .data(nodes.filter(function(d){return d.depth==2}))
  .enter().append("text")
  .attr("class", "length-label")
  .attr("id", function(d){ return "numSTK-"+d.data.id })
  .text(function(d) { return d.data.children.length; })
  .attr("text-anchor","middle")
  ;
        
g.selectAll("circle").on("click", function(d) {
    this.classList.toggle("node-selected");
});

var node = g.selectAll("circle,text");
node.attr("transform", function(d) { return "translate(" + d.x  + "," + d.y + ")"; });
.circles{
    width:100%;
    background-color: #fff;
    padding: 15px;
}
.root {
    fill: #eee;
}
.node {
    cursor: pointer;
    fill: #e6e6e6;
    overflow: hidden;
    stroke-width: 0px;
}
.node:hover {
    stroke: #000;
    fill: #fff;
    stroke-width: 8px;
}
.node-selected {
    stroke:#000;
}
.node.node--leaf {
    fill: #fff;
    display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>

<div class="circles" id="circles">

Upvotes: 0

Tom Shanley
Tom Shanley

Reputation: 1787

You could use :hover in your CSS on your circle, and within that set the stroke colour to black. See the circle on the left in the snippet below.

mix-blend-mode can be applied to the circle, but not sure how you would get a black stroke using that method. See the circle on the right in the snippet below. Also, mix-blend-mode isn't supported in all browsers.

body {
  background: grey;
}

circle {

  fill: orange;
  stroke: DarkOrange;
  stroke-width: 2px;

}

circle.stroke-color:hover {

  stroke: black;

}

circle.mix-blend-mode:hover {

  mix-blend-mode: multiply;

}
<svg width="500" height="500">

  <circle class="stroke-color" cx="100" cy="75" r="50"/>
  <circle class="mix-blend-mode" cx="300" cy="75" r="50"/>

</svg>

Upvotes: -1

Related Questions