在上一章的柱状图基础上,我们增加了交互功能,让图表能够响应用户的操作。下面我将详细解释交互式操作的实现方式,并展示如何为下一章的饼图做准备。
一、交互式操作的核心概念
D3.js 的交互式操作主要通过事件监听来实现,语法与 jQuery 类似:
selection.on('eventName', function(){ ... })
-
第一个参数:要监听的事件名称(如
click
,mouseover
,mouseout
等) -
第二个参数:事件触发时要执行的函数
二、当前柱状图的交互实现
在现有代码中,我们为矩形元素添加了两个事件监听器:
.on('mouseover',function () { // 鼠标移入事件
d3.select(this) // 这里的this指向当前矩形元素
.transition() // 添加过渡效果
.duration(1000) // 过渡持续时间1秒
.delay(200) // 延迟200毫秒开始
.attr('fill','green'); // 最终变为绿色
})
.on('mouseout',function () { // 鼠标移出事件
d3.select(this)
.transition()
.duration(1000)
.delay(200)
.attr('fill','pink'); // 恢复为粉色
})
三、交互效果的增强建议
1. 添加点击事件:
可以为柱状图添加点击事件,显示更多数据细节
2. 添加工具提示:
当鼠标悬停时显示数值提示框
3. 动画效果优化:
可以尝试不同的缓动函数(easing)让动画更自然
四、为饼图做准备
1. 鼠标悬停高亮: 当鼠标悬停在某个扇形上时,可以将其突出显示
2. 点击事件: 点击扇形可以展开显示详细信息
3. 过渡动画: 扇形的大小变化可以添加平滑的过渡效果
五、交互式柱状图代码示例
👇 完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>交互式柱状图</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
<style>
.tooltip {
position: absolute;
padding: 8px;
background: rgba(0, 0, 0, 0.8);
color: white;
border-radius: 4px;
pointer-events: none;
font-size: 12px;
}
</style>
</head>
<body>
<svg width="500" height="400"></svg>
<div class="tooltip" style="opacity: 0;"></div>
</body>
<script>
var data = [90,75,12,36,54,88,24,66];
var margin = 30;//svg 上下左右边距
var svg = d3.select('svg');
var width = svg.attr('width');
var height = svg.attr('height');
var tooltip = d3.select('.tooltip');
//创建分组
var g = svg.append('g').attr('transform','translate('+ margin +','+ margin +')');
//定义 x y 轴比例尺
var scaleX = d3.scaleBand()
.domain(d3.range(data.length))
.range([0,width - margin*2]);
var scaleY = d3.scaleLinear()
.domain([0,d3.max(data)])
.range([height - margin*2,0]);
//绘画 x y 轴
var axisX = d3.axisBottom(scaleX);
var axisY = d3.axisLeft(scaleY);
g.append('g').attr('transform','translate(0,'+ (height - margin*2) +')').call(axisX);
g.append('g').attr('transform','translate(0,0)').call(axisY);
// 创建矩形分组
var gs = g.selectAll('rect').data(data).enter().append('g');
//绘 柱状图 + 交互效果
var rectP = 10;//柱状图间距
gs.append('rect')
.attr('x',function (d,i) {
return scaleX(i) + rectP/2;
})
.attr('y',function (d,i) {
return scaleY(d);
})
.attr('width',function (d,i) {
return scaleX.step() - rectP;
})
.attr('height',function (d,i) {
return height - margin*2 - scaleY(d);
})
.attr('fill','pink')
// 添加鼠标交互事件
.on('mouseover',function (d, i) {
// 高亮当前柱形
d3.select(this)
.transition()
.duration(300)
.attr('fill','green');
// 显示工具提示
tooltip.transition()
.duration(300)
.style('opacity', 1);
tooltip.html("数值: " + d)
.style('left', (d3.event.pageX + 10) + 'px')
.style('top', (d3.event.pageY - 20) + 'px');
})
.on('mouseout',function () {
// 恢复颜色
d3.select(this)
.transition()
.duration(300)
.attr('fill','pink');
// 隐藏工具提示
tooltip.transition()
.duration(300)
.style('opacity', 0);
})
.on('click', function(d, i) {
alert("你点击了第 " + (i+1) + " 个柱形,数值为: " + d);
});
//绘 文字 + 过度效果
gs.append('text')
.attr('x',function (d,i) {
return scaleX(i) + rectP/2;
})
.attr('y',function (d,i) {
return scaleY(d);
})
.attr('dx',function (d,i) {
return 12.5;
})
.attr('dy',function (d,i) {
return 20;
})
.text(function (d,i) {
return d;
})
.transition()
.duration(2000)
.delay(function (d,i) {
return i*300;//300毫秒
})
.attr('y',function (d,i) {
return scaleY(d);
});
</script>
</html>
👇 实现效果:
小结
核心要点
1. 事件监听机制:
-
使用
on('eventName', callback)
方法实现交互 -
支持多种事件类型(
mouseover
/mouseout
/click
等) -
回调函数中的
this
指向当前DOM元素
2. 过渡动画效果:
-
通过
transition()
方法创建平滑过渡 -
可配置参数:
duration()
控制动画时长delay()
设置延迟执行ease()
指定缓动函数(默认cubic-in-out
)
3. 典型交互模式:
-
鼠标悬停高亮(
mouseover/mouseout
) -
点击响应(
click
) -
工具提示显示(配合HTML/CSS实现)
下章预告:将这些交互技术应用于饼图实现
-
d3.arc()
生成器的工作原理 -
饼图布局(
d3.pie()
)的数据转换 -
扇形元素的交互特效实现
-
标签位置的自适应计算