具有数据值的dataLabels下如何计算X和Y坐标是动态的。
这是我的JSfiddle
https://jsfiddle.net/BlackLabel/ay5mbfew/
{
name: 'Incorrect',
legendColor: 'green',
dataLabels: {
enabled: true,
zIndex: 3,
y: -150,
x: 90,
borderWidth: 0,
overflow: 'allow',
style: {
fontSize: 60
}
},
data: [{
color: 'green',
radius: '112%',
innerRadius: '65%',
y: 40
}]
}]
如果更改了值,则如何根据值计算x,y坐标,以使文本相应地显示在条形上
谢谢
最佳答案
可以以更简单的方式完成此类图表。我不是使用复杂的路径,而是使用带有stroke-dasharray和stroke-dashoffset的圆。
我在不使用Highcharts的情况下这样做-您可能不喜欢这样
另外,我建议删除线条的圆度,因为这会引起混淆。在我的代码中,如果要删除圆度,则需要从CSS中删除它:stroke-linecap: round;
请阅读我的代码中的注释。
var SVG_NS = 'http://www.w3.org/2000/svg';
let r = bg.getAttribute("r");//the radius of the chart
let items = [ {val:.17,color:"red"}, {val:.35,color:"hotpink"}, {val:.25,color:"gold"}, {val:.12,color:"skyblue"} ];//<--- change this
// the total length of the circle
let totalLength = bg.getTotalLength()
for(let i = items.length-1; i >=0 ; i--){
//the previous item in the array
let prev = getPrev(i);
// for every item in the items array calculate the value for the stroke-dasharray, stroke-dashoffset
let o = {
r:r,
"stroke-dasharray":totalLength,
"stroke-dashoffset": totalLength,
"style": `--sdo:${totalLength * (1 - items[i].val)}`,
stroke:items[i].color,
transform: `rotate(${prev * 360})`,
class:"animatable"
}
//draw the circles
drawSVGelmt(o,"circle", circles)
// calculate the position for the text
// first get the angle in the middle
let textAngle = 2*Math.PI * (prev + items[i].val/2);
// get the position and rotate the text
let t = {}
t.x=r*Math.cos(textAngle);
t.y=r*Math.sin(textAngle);
t.transform= `rotate(${90},${t.x},${t.y})`
//draw the text
let _text = drawSVGelmt(t,"text", text);
// add the text content
_text.textContent = `${items[i].val * 100}%`;
}
// a function to draw an svg element
function drawSVGelmt(o,tag, parent) {
var elmt = document.createElementNS(SVG_NS, tag);
for (var name in o) {
if (o.hasOwnProperty(name)) {
elmt.setAttributeNS(null, name, o[name]);
}
}
parent.appendChild(elmt);
return elmt;
}
// a function to get the previous item in the array
function getPrev(i){
let prev = 0;
if(i > 0){
for(let j = 0; j < i; j++){
prev += items[j].val
}
}
return prev;
}
svg {
border: 1px solid;
transform: rotate(-90deg);
}
circle {
fill: none;
stroke-width: 60;
stroke-linecap: round;
}
circle.animatable {
animation: dash 0.5s ease-in forwards;
}
text {
fill: black;
stroke: white;
paint-order: stroke;
stroke-width: 5;
font-size: 50px;
font-family: arial;
font-weight: bold;
text-anchor: middle;
dominant-baseline: middle;
}
@keyframes dash {
to {
stroke-dashoffset: var(--sdo);
}
}
<svg id="svg" width="400" viewBox="-200 -200 400 400">
<circle id="bg" r="150" stroke="#d9d9d9" />
<g id="circles"></g>
<g id="text"></g>
</svg>