问题描述
我是 Javascript 新手,我一直在为这个项目构建雷达/网络图。
如图所示,该图是衡量基础攻击、防御和耐力的三点雷达图。我希望在这些点上叠加一个三角形(或另一个多边形)以显示“雷达”的清晰形状:
。此数据通过 API 调用并通过 sqlite 部署。 API 需要输入特定的 ID 号才能生成相关的基本统计信息。
下面的代码构成了图表:
function getBaseStats(pokecharID) {
var queryUrl = "/api/v1/base_stats";
var int_pokeCharID = parseInt(pokecharID);
let filteredStats = [];
let statsList = [];
statsList.length = 0;
d3.json(queryUrl).then((data) => {
filteredStats.push(
data.filter((stat) => stat[0] === int_pokeCharID && stat[1] === "normal")
);
var base_attack = filteredStats[0][0][2];
var base_defense = filteredStats[0][0][3];
var base_stamina = filteredStats[0][0][4];
var w = 500,h = 500;
var colorscale = d3.scaleOrdinal(d3.schemeCategory10);
var d = [
[
{ axis: "Base Attack",value: base_attack },{ axis: "Base Defense",value: base_defense },{ axis: "Base Stamina",value: base_stamina },],];
感谢所有帮助!
var area = d3.svg.area.radial()
.interpolate("cardinal-closed")
.angle(function(d) { return angle(d.time); })
.innerRadius(function(d) { return radius(d.y0); })
.outerRadius(function(d) { return radius(d.y0 + d.y); });
解决方法
有一个例子,根据您的要求做了一些修改:
const data = [
{color: 'orange',values: [500,400,900]},{color: 'blue',values: [800,200,400]},{color: 'green',values: [300,1000,600]},];
const svg = d3.select('svg');
const maxValue = 1000;
const radius = 150;
const center = {x: 250,y: 200};
const radialScale = d3.scaleLinear()
.domain([0,maxValue])
.range([radius,0])
const axis = d3.axisRight()
.scale(radialScale)
.ticks(5)
svg.append('g')
.attr('transform',`translate(${center.x},${center.y - radius})`)
.call(axis);
let val,angle;
for (val = 0; val <= maxValue; val += maxValue / 5) {
const r = radialScale(val);
svg.append('circle')
.attr('cx',center.x)
.attr('cy',center.y)
.attr('r',r)
.style('stroke','#aaa')
.style('fill','none');
}
const labels = ['Base Attack','Base Stamina','Base Defence'];
const anchors = ['middle','start','end'];
const shifts = [{x: 0,y: -15},{x: 10,y: 15},{x: -10,y: 15}];
for (let index = 0; index < labels.length; index++) {
const angle = index * Math.PI * 2 / labels.length;
const x = center.x + radius * Math.sin(angle);
const y = center.y + radius * -Math.cos(angle);
if (angle > 0) {
svg.append('line')
.attr('x1',center.x)
.attr('y1',center.y)
.attr('x2',x)
.attr('y2',y)
.style('stroke','#000');
}
svg.append('text')
.text(labels[index])
.attr('text-anchor',anchors[index])
.attr('dx',shifts[index].x)
.attr('dy',shifts[index].y)
.attr('x',x)
.attr('y',y)
}
data.forEach(({color,values},index) => {
let path = '';
for (let i = 0; i < values.length; i++) {
const r = radius - radialScale(values[i]);
console.log('V: ',values[i]);
console.log('R: ',r);
const angle = i * Math.PI * 2 / values.length;
const x = center.x + r * Math.sin(angle);
const y = center.y + r * -Math.cos(angle);
path += `${i > 0 ? 'L' : 'M'} ${x},${y} `;
}
path += 'Z';
svg.append('path')
.attr('d',path)
.style('stroke',color)
.style('stroke-width',3)
.style('stroke-opacity',0.6)
.style('fill',color)
.style('fill-opacity',0.3)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
<svg width="500" height="400">
</svg>