我正在尝试创建一个环,这个环使用 d3.js,但我遇到了一个问题,当环或弧完成完整时,我想偏移一点,以便它看起来像是在自身之上。
这就是我想要实现的目标:
...这就是我得到的:
。这是我的代码
this my js code:
/* Define properties */
const width = 500;
const height = 500;
const margin = 40;
const circleStroke = 50;
const circleSpace = 2;
const radius = (width - margin) / 2;
const fullCircle = Math.PI * 2;
const configurations = [
{color: 'hotpink',percentage:0.5},
{color: 'limegreen',percentage:0.6},
{color: 'turquoise',percentage:0.9}
];
/* Add SVG inside <div id="activity"></div> */
const canvas = d3.select('#activity')
.append('svg')
.attr('width', width)
.attr('height', height)
/* Chart configuration. */
filter = canvas.append("defs")
.append("filter")
.attr("id", "drop-shadow")
.attr("height", "130%"); // Adjust this value to control the shadow spread
filter.append("feGaussianBlur")
.attr("in", "SourceAlpha")
.attr("stdDeviation", 5); // Adjust the stdDeviation value to control the blur intensity
filter.append("feOffset")
.attr("dx", 0)
.attr("dy", 5)
.attr("result", "offsetblur");
var feMerge = filter.append("feMerge");
feMerge.append("feMergeNode");
feMerge.append("feMergeNode")
.attr("in", "SourceGraphic");
const rings = canvas.append('g')
.attr('transform', `translate(${width / 2}, ${height / 2})`);
/* Chart configuration. */
arcs = [];
configurations.forEach((ring,index) =>{
var arc = d3.arc()
.innerRadius(radius - circleStroke * (index + 1) - circleSpace * index)
.outerRadius(radius - circleStroke * index - circleSpace * index)
.cornerRadius(50)
.startAngle(0)
.endAngle(fullCircle*ring.percentage);
arcs.push(arc); // Store arc generators in the array
rings.append("path")
.attr("fill",ring.color)
.attr("d",arc);
});
// Dynamically chaninging the the value of the rings
// Array of input elements
const inputElements = [
document.getElementById("ring1"),
document.getElementById("ring2"),
document.getElementById("ring3")
];
inputElements.forEach((inputElement,index)=>{
inputElement.addEventListener("input",()=>{
var ringPercentage = +(inputElement.value/100);
arcs[index].endAngle(fullCircle * ringPercentage); // Update the end angle of the first arc
console.log(ringPercentage);
rings.select(`path:nth-child(${index + 1})`)
.attr("fill",configurations[index].color)
.style("filter", "url(#drop-shadow)")
.attr("d", arcs[index]);
// console.log(arcs[index].endAngle());
if(ringPercentage==1){
// create and append a new path to the ring
rings.append("path");
}
if(ringPercentage>1){
// create a new arc
var arc_new = d3.arc()
.innerRadius(radius - circleStroke * (index + 1) - circleSpace * index)
.outerRadius(radius - circleStroke * index - circleSpace * index)
.cornerRadius(50)
.startAngle(0)
.endAngle(fullCircle*(ringPercentage-1));
// get only needed path by 1 ring => 4, 2 ring=> 5,3 ring 6
switch (inputElement.id) {
case "ring1":
rings.select(`path:nth-child(4)`)
.attr("fill",configurations[index].color)
.attr("d", arc_new)
.style("filter", "url(#drop-shadow)");
break;
case "ring2":
rings.select(`path:nth-child(5)`)
.attr("fill",configurations[index].color)
.attr("d", arc_new)
.style("filter", "url(#drop-shadow)");
break;
case "ring3":
rings.select(`path:nth-child(6)`)
.attr("fill",configurations[index].color)
.attr("d", arc_new)
.style("filter", "url(#drop-shadow)");
break;
}
}
})
})
// Define the shadow filter
// Define the filter for the shadow effect
and the my html code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ring v2</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<div>
<label for="ring1">Ring 1:</label>
<input type="range" id="ring1" class="ring-range" min="0" max="150" step="1" value="70" />
</div>
<div>
<label for="ring2">Ring 2:</label>
<input type="range" id="ring2" class="ring-range" min="0" max="100" step="1" value="90" />
</div>
<div>
<label for="ring3">Ring 3:</label>
<input type="range" id="ring3" class="ring-range" min="0" max="150" step="1" value="40" />
</div>
<div id="activity"></div>
<script src="test.js"></script>
</html>
我的想法是创建一个单独的弧线,它将超越旧的弧线,但遵循相同的路径,但我的新弧线的开始并未与前一个弧线合并
这是一个尝试:
const drawCircle = (container, fullAngle, radius, width, startRGB, endRGB) => {
const delta = 0.01;
const steps = fullAngle / delta;
for (let step = 0; step <= steps; step++) {
const angle = step * delta;
const x = radius * Math.sin(angle);
const y = radius * -Math.cos(angle);
const r = Math.floor((endRGB[0] - startRGB[0]) / steps * step) + startRGB[0];
const g = Math.floor((endRGB[1] - startRGB[1]) / steps * step) + startRGB[1];
const b = Math.floor((endRGB[2] - startRGB[2]) / steps * step) + startRGB[2];
const color = `rgb(${r},${g},${b})`;
container.append('circle')
.attr('cx', x)
.attr('cy', y)
.attr('r', width / 2)
.attr('stroke', 'none')
.attr('fill', color);
}
}
drawCircle(d3.select('#first'), Math.PI * 2 / 3, 80, 30, [0, 64, 192], [255, 64, 64]);
drawCircle(d3.select('#second'), Math.PI * 4 / 3, 80, 30, [255, 32, 32], [32, 192, 255]);
drawCircle(d3.select('#third'), Math.PI * 2, 80, 30, [32, 192, 32], [32, 32, 255]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width='600' height='200'>
<g id='first' transform='translate(100,100)'>
</g>
<g id='second' transform='translate(300,100)'>
</g>
<g id='third' transform='translate(500,100)'>
</g>
</svg>