前面写了一篇 # 【d3.js入门】基本雷达图,这次我们在这个面积图基础上添加一些动画效果。
好,废话多说,我们继续绘制一个基本雷达图。 雷达图,又称为蜘蛛图或星形图,是一种用于在二维平面上显示多变量数据的数据可视化技术。它特别适用于比较不同类别之间的多个变量。
步骤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()
方法将文本内容更新为包含名称和值的字符串。
这样,当点击按钮时,数据就会更新并在图表中显示出来。希望这可以帮助你进一步改进你的雷达图!
好了,最后是源码和演示地址: