我正在研究雷达图表,我需要在每个弧内显示一些圆圈。我可以在任何给定的时间点(内半径,外半径,起始角和终止角)获得以下信息。 有了这些信息,我需要在这个封闭的弧形路径中添加一些圆圈。请让我知道如何实现这一目标。
以下是我想要实现的示例image:
var width = 600;
var height= 600;
var radius = 300;
var color = d3.scale.category20b();
var svg = d3.select("#radarchart")
.append("svg")
.attr("height",height)
.attr("width",width);
var radargroup = svg.append("g").attr('transform','translate('+ (width/2)+','+(height/2)+')');
var p = Math.PI *2;
var innercircles=3;
var innerradius = [200,100,0];
var outerradius =[radius, radius - 100,radius - 200];
var startangle = [0 ,25,50,75];
var endangle = [25,50,75,100]
var fillcolor = ['#E4E5E4','#D7D8D6','#BFC0BF'];
var counter = 0;
svg.append("rect")
.attr("x",width/2 - 7)
.attr("y","0")
.attr("width","15px")
.attr("height",height)
.style("fill","#fff")
.style("opacity",0.5);
var labelcontainer = svg.append("g").attr('transform',"translate(0,"+(height/2 - 10 )+')');
labelcontainer.append("rect")
.attr("x","0")
.attr("y","0")
.attr("width",width)
.attr("height","15px")
.style("fill","#fff")
.style("opacity",0.5);
var data = [
{
"name":"A",
"status":[
{
"statusname":"section1",
"statusvalue":[
{
"radar_id":"1",
"radar_value":"Consumer-driven contract testing"
},
{
"radar_id":"2",
"radar_value":"NoPSD"
}
]
},
{
"statusname":"section2",
"statusvalue":[
{
"radar_id":"4",
"radar_value":"BEM"
},
{
"radar_id":"5",
"radar_value":"NPM for all the things"
}
]
},
{
"statusname":"section3",
"statusvalue": null
}
]
},
{
"name":"B",
"status":[
{
"statusname":"section1",
"statusvalue":null
},
{
"statusname":"section2",
"statusvalue":null
},
{
"statusname":"section3",
"statusvalue":[
{
"radar_id":"6",
"radar_value":"Composer"
},
{
"radar_id":"7",
"radar_value":" Postman"
}
]
}
]
},
{
"name":"C",
"status":[
{
"statusname":"section1",
"statusvalue":null
},
{
"statusname":"section2",
"statusvalue":[
{
"radar_id":"10",
"radar_value":"H2O"
}
]
},
{
"statusname":"section3",
"statusvalue":null
}
]
},
{
"name":"D",
"status":[
{
"statusname":"section1",
"statusvalue":null
},
{
"statusname":"section2",
"statusvalue":null
},
{
"statusname":"section3",
"statusvalue":[
{
"radar_id":"12",
"radar_value":"ECMAScript 6"
},
{
"radar_id":"13",
"radar_value":"React"
}
]
}
]
}
];
var myScale = d3.scale.linear().domain([0, 100]).range([0, 2 * Math.PI]);
data.map(function(quadrant,index){
var svgquadrant = radargroup.append("g").attr("id","quadrant"+index);
//creating arcs in each quadrant
quadrant.status.map(function(eachstate,i){ console.log(eachstate);
counter = counter + 1;
var arcname = "arc" + counter;
arcname = d3.svg.arc()
.innerRadius(innerradius[i])
.outerRadius(outerradius[i])
.startAngle(myScale(startangle[index]))
.endAngle(myScale(endangle[index]));
svgquadrant.append("path").attr('id','p'+index+i).attr("d", arcname).attr('fill',fillcolor[i]);
if(eachstate.statusvalue != null){
var strlen = 20;
// logic goes here
}
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="radarchart">
</div>
答案 0 :(得分:0)
你真正要问的是半径和角度,我如何计算圆(弧)上的x,y位置。这只是simple trigonometry。
使用你的变量,这个数学成为:
var r = (innerradius[i] +outerradius[i]) / 2,
a = (myScale(startangle[index]) + myScale(endangle[index])) / 2 - (Math.PI /2),
coors = [Math.cos(a) * r, Math.sin(a) * r];
如果您只有一个圈子,
d3
提供了一个带有弧的辅助函数来计算centroid(基本上是上面的数学运算)。这恰好是放置圈子的一个非常方便的地方:
if (eachstate.statusvalue != null) {
var strlen = 20;
var coors = arcname.centroid();
svgquadrant.append('circle')
.style('fill','red')
.attr('r', 20)
.attr('cx', coors[0])
.attr('cy', coors[1]);
}
如果你有一个以上的圆圈,你必须“抖动”这个角度,使它们彼此分开。类似的东西:
for (var j = 0; j < eachstate.statusvalue.length; j++){
var r = (innerradius[i] +outerradius[i]) / 2,
a = (myScale(startangle[index]) + myScale(endangle[index])) / 2 - (Math.PI /2);
a += (0.436332 * j); // 25 degrees apart
coors = [Math.cos(a) * r, Math.sin(a) * r];
}
完整代码:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>
<body>
<div id="radarchart">
</div>
<script>
var width = 600;
var height = 600;
var radius = 300;
var color = d3.scale.category20b();
var svg = d3.select("#radarchart")
.append("svg")
.attr("height", height)
.attr("width", width);
var radargroup = svg.append("g").attr('transform', 'translate(' + (width / 2) + ',' + (height / 2) + ')');
var p = Math.PI * 2;
var innercircles = 3;
var innerradius = [200, 100, 0];
var outerradius = [radius, radius - 100, radius - 200];
var startangle = [0, 25, 50, 75];
var endangle = [25, 50, 75, 100]
var fillcolor = ['#E4E5E4', '#D7D8D6', '#BFC0BF'];
var counter = 0;
svg.append("rect")
.attr("x", width / 2 - 7)
.attr("y", "0")
.attr("width", "15px")
.attr("height", height)
.style("fill", "#fff")
.style("opacity", 0.5);
var labelcontainer = svg.append("g").attr('transform', "translate(0," + (height / 2 - 10) + ')');
labelcontainer.append("rect")
.attr("x", "0")
.attr("y", "0")
.attr("width", width)
.attr("height", "15px")
.style("fill", "#fff")
.style("opacity", 0.5);
var data = [{
"name": "A",
"status": [{
"statusname": "section1",
"statusvalue": [{
"radar_id": "1",
"radar_value": "Consumer-driven contract testing"
}, {
"radar_id": "2",
"radar_value": "NoPSD"
}]
},
{
"statusname": "section2",
"statusvalue": [{
"radar_id": "4",
"radar_value": "BEM"
}, {
"radar_id": "5",
"radar_value": "NPM for all the things"
}]
}, {
"statusname": "section3",
"statusvalue": null
}
]
}, {
"name": "B",
"status": [{
"statusname": "section1",
"statusvalue": null
}, {
"statusname": "section2",
"statusvalue": null
}, {
"statusname": "section3",
"statusvalue": [{
"radar_id": "6",
"radar_value": "Composer"
}, {
"radar_id": "7",
"radar_value": " Postman"
}]
}]
}, {
"name": "C",
"status": [{
"statusname": "section1",
"statusvalue": null
}, {
"statusname": "section2",
"statusvalue": [{
"radar_id": "10",
"radar_value": "H2O"
}]
}, {
"statusname": "section3",
"statusvalue": null
}]
}, {
"name": "D",
"status": [{
"statusname": "section1",
"statusvalue": null
}, {
"statusname": "section2",
"statusvalue": null
}, {
"statusname": "section3",
"statusvalue": [{
"radar_id": "12",
"radar_value": "ECMAScript 6"
}, {
"radar_id": "13",
"radar_value": "React"
}]
}]
}];
var myScale = d3.scale.linear().domain([0, 100]).range([0, 2 * Math.PI]);
data.map(function(quadrant, index) {
var svgquadrant = radargroup.append("g").attr("id", "quadrant" + index);
//creating arcs in each quadrant
quadrant.status.map(function(eachstate, i) {
//console.log(eachstate);
counter = counter + 1;
var arcname = "arc" + counter;
arcname = d3.svg.arc()
.innerRadius(innerradius[i])
.outerRadius(outerradius[i])
.startAngle(myScale(startangle[index]))
.endAngle(myScale(endangle[index]));
svgquadrant.append("path").attr('id', 'p' + index + i).attr("d", arcname).attr('fill', fillcolor[i]);
if (eachstate.statusvalue != null) {
var strlen = 20;
var N = eachstate.statusvalue.length;
for (var j = 0; j < N; j++){
var r = (innerradius[i] +outerradius[i]) / 2,
a = (myScale(startangle[index]) + myScale(endangle[index])) / 2 - (Math.PI /2);
a += (0.436332 * j);
var coors = [Math.cos(a) * r, Math.sin(a) * r];
svgquadrant.append('circle')
.style('fill','red')
.attr('r', 10)
.attr('cx', coors[0])
.attr('cy', coors[1]);
}
}
});
})
</script>
</body>
</html>