[SVG]ドーナツ状のcircleを描画する。
先日の勉強会にて「重ねたcircleの途中の色だけ変えたい」という質問があり、その場では詳しい方法を答えることができなかったので、記事にて回答します。
複数のcircleを重ねて色を変えた場合、透過処理を行うと下のcircleの色と重なってしまいます。
これを回避する方法はいろいろあるのですが、一番簡単な方法はmaskを使う方法です。
(質問には「クリップパスでできると思います」と答えた気がするのですが、すみません私の勘違いでした。クリップパスは「表示したい部分を切り取る」だけなので、Maskを使う必要があります)
サークルをMaskを使ってドーナツ状に変形することで、重ねたときに色が重ならなくなります。
Mask機能を使ってドーナツ状のcircleを表示する
D3.jsを使てドーナツ状のcircleを重ねるサンプルです。
データセットの数に合わせてmask要素を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
const dataSet =[ {r:20, color:"blue"}, {r:40, color:"red"}, {r:60, color:"blue"}, ] /*normal*/ const svg1 = d3.select("#svg1") svg1.selectAll("circle") .data(dataSet.reverse()) .enter() .append("circle") .attr("cx", 100) .attr("cy", 60) .attr("r", d => d.r) .attr("fill", d => d.color) /*fill-opacity:0.5*/ const svg2 = d3.select("#svg2") svg2.selectAll("circle") .data(dataSet.reverse()) .enter() .append("circle") .attr("cx", 100) .attr("cy", 60) .attr("r", d => d.r) .attr("fill", d => d.color) .attr("fill-opacity", 0.5) /*mask*/ const svg3 = d3.select("#svg3") svg3.selectAll("circle") .data(dataSet) .enter() .append("circle") .attr("cx", 100) .attr("cy", 60) .attr("r", d => d.r) .attr("fill", d => d.color) .attr("fill-opacity", 0.5) .attr("mask", (d, i) => { if(i <= 0) return null; return `url(#mask${i}`; }) //部品の定義 const defs = svg3.append("defs"); dataSet.forEach(function(d, i){ if (i <= 0) return; //defs内にmask要素を追加 const mask = defs.append("mask") .attr("id", `mask${i}`); //mask表示領域の指定 mask.append("circle") .attr("cx", 100) .attr("cy", 60) .attr("r", dataSet[i].r) .attr("fill", "white") //mask非表示領域の指定 mask.append("circle") .attr("cx", 100) .attr("cy", 60) .attr("fill", "black") .attr("r", dataSet[i-1].r) }); |