【d3.js入门】基本雷达图动画

1,979 阅读3分钟

前面写了一篇 # 【d3.js入门】基本雷达图,这次我们在这个面积图基础上添加一些动画效果。

雷达图.gif

好,废话多说,我们继续绘制一个基本雷达图。 雷达图,又称为蜘蛛图或星形图,是一种用于在二维平面上显示多变量数据的数据可视化技术。它特别适用于比较不同类别之间的多个变量。

步骤1:设置HTML结构 首先,让我们为我们的雷达图设置基本的HTML结构。

let dom = document.createElement('div');
document.body.appendChild(dom);

// 创建一个SVG元素
let svg = d3.select(dom)
    .append("svg")
    .attr("width", svgWidth)
    .attr("height", svgHeight)
    .style('border', '1px solid #999999');

步骤2:定义数据 接下来,让我们定义要在雷达图中可视化的数据。在这个例子中,我们有一个由科目和相应值组成的数据集。

let dataset = [
    { name: "数学", value: 98 },
    { name: "语文", value: 90 },
    { name: "英语", value: 80 },
    { name: "物理", value: 85 },
    { name: "化学", value: 85 },
    { name: "生物", value: 90 }
];

步骤3:配置图表属性 现在,让我们配置雷达图的属性,如填充、宽度、高度和半径。

let padding = 50;
let svgWidth = 600;
let svgHeight = 400;
let centerX = svgWidth / 2; // 中心点x坐标
let centerY = svgHeight / 2; // 中心点y坐标
let radius = Math.min(centerX, centerY) - padding; // 半径

步骤4:创建比例尺 为了在图表上定位数据点,我们需要创建比例尺。在这个例子中,我们将使用线性比例尺来处理角度,并使用另一个线性比例尺来处理数值。

// 角度比例尺
let angleScale = d3.scaleLinear()
    .domain([0, numTicks])
    .range([0, Math.PI * 2]);

// 数值比例尺
let valueScale = d3.scaleLinear()
    .domain([0, 100])
    .range([0, radius]);

步骤5:绘制图表 现在我们已经准备好了一切,让我们开始绘制我们的雷达图。我们首先创建一个用作背景形状的多边形。

// 创建用于背景形状的多边形
let polygon = svg.append("g")
    .attr("class", "polygon");

let hexagon = polygon.append("polygon")
    .attr("points", function () {
        let points = "";
        for (let i = 0; i < numTicks; i++) {
            let angle = angleScale(i);
            let x = centerX + valueScale(100) * Math.sin(angle);
            let y = centerY - valueScale(100) * Math.cos(angle);
            points += x + "," + y + " ";
        }
        return points;
    })
    .attr("stroke", "#f6efa6")
    .attr("stroke-width", 5)
    .attr("fill", "url(#gradient)");

步骤6:绘制数据线 接下来,让我们绘制连接图表上数据点的数据线。

// 绘制数据线
let line = d3.line()
    .x(function (d, i) { return centerX + valueScale(d.value) * Math.sin(angleScale(i)); });
    .y(function (d, i) { return centerY - valueScale(d.value) * Math.cos(angleScale(i)); })
    .curve(d3.curveLinearClosed);
svg.append("path")
    .datum(dataset)
    .attr("fill", "#ffffff")
    .attr("fill-opacity", 0.5)
    .attr("stroke", "#fff")
    .attr("stroke-width", 2)
    .attr("d", line);

// 绘制轴标签
let labels = svg.append("g")
    .attr("class", "labels");
for (let i = 0; i < numTicks; i++) {
    let angle = angleScale(i);
    let r = radius + padding * 0.5;
    let x = centerX + r * Math.sin(angle);
    let y = centerY - r * Math.cos(angle);
    labels.append("text")
        .attr("x", x)
        .attr("y", y)
        .attr("text-anchor", "middle")
        .attr("fill", "#333333")
        .text(dataset[i].name + " " + dataset[i].value);
}

最后是更新数据。呵呵,这次我们只保留的更新数据按钮,其他的都不要。 因为排序在雷达图中是常用,雷达图轴一般固定图例,所以不要轻易更改,不然就不是可视化了。 而数据的增加和删除也不适用于雷达图。 雷达图适合展示固定维度的数据。

// 更新数据
buts[0].onclick = function () {
dataset.forEach(item => {
   item.value = Math.floor(Math.random() * 60) + 40;
})
svg.selectAll("path")
   .datum(dataset)
   .transition()
   .duration(1000)
   .attr("d", line);

svg.selectAll("text")
   .data(dataset)
   .transition()
   .duration(1000)
   .text(function (d) { return d.name + " " + d.value; });

}

这段代码片段是用于更新雷达图中的数据。当点击 buts[0] 元素时,会随机生成新的数据值,并使用过渡效果将路径和标签进行更新。

首先,对 dataset 数组中的每个项进行遍历,将其 value 属性设置为一个随机数。接下来,通过选择所有的路径元素并使用 .datum() 方法将新的数据集绑定到它们上面。然后,使用 .transition() 方法以及 .duration() 指定过渡持续时间,并使用 .attr("d", line) 更新路径的 d 属性,从而绘制新的数据线。

接着,选择所有的文本元素并使用 .data() 方法绑定新的数据集。然后,使用 .transition().duration() 方法指定过渡持续时间,并使用 .text() 方法将文本内容更新为包含名称和值的字符串。

这样,当点击按钮时,数据就会更新并在图表中显示出来。希望这可以帮助你进一步改进你的雷达图!

好了,最后是源码和演示地址:

scqilin.github.io/d3js/basic-…