Javascript/D3 - 绘制雷达图

问题描述

我是 Javascript 新手,我一直在为这个项目构建雷达/网络图。

Radar Graph

如图所示,该图是衡量基础攻击、防御和耐力的三点雷达图。我希望在这些点上叠加一个三角形(或另一个多边形)以显示“雷达”的清晰形状:

此数据通过 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>