参考:
【D3.js】基础教程-CSDN博客
https://blog.csdn.net/weixin_39085822/article/details/119755130
D3 by Observable | The JavaScript library for bespoke data visualization
https://d3js.org/
目录
- 动态方法
- 柱状图上文字跳动实例
- 交互式操作
动态方法
- transition()
是指从状态A变到状态B,d3会自动计算。比如从颜色A过渡到颜色B,d3会自动插值。 - duration()
指定过渡的时间,单位为毫秒 - ease()
指定过渡的方式,比如.ease(d3.easeLinear)
是普通的线性变换,.ease(d3.easeBounce)
是弹跳着变换。变换方式有很多,看:https://d3js.org/d3-ease#easeLinear - delay()
指定延迟时间,表示经过一定时间后才开始转换。单位是毫秒。如果要对整体做延迟就放在最后并给一个固定值;如果需要对所有图形进行不同的延迟,可以用匿名函数(function(d, i)
)
var body = d3.select("body"); //选择文档中的body元素
var svg = body.select("svg"); //选择body中的svg元素
var circle1 = svg.append("circle").attr("cx", 100).attr("cy", 100).attr("r", 45).style("fill", "green");
//在1秒(1000毫秒)内将圆心坐标由100变为300
circle1.transition().duration(1000).ease(d3.easeLinear).attr("cx", 300) // 改属性.style("fill", "red");
柱状图上文字跳动实例
效果:
<script src="https://d3js.org/d3.v7.min.js"></script><script>//画布大小var width = 400;var height = 400;//在 body 里添加一个 SVG 画布 var svg = d3.select("body").append("svg").attr("width", width).attr("height", height);//画布周边的空白var padding = {left:30, right:30, top:20, bottom:20};// 定义数据var dataset = [10, 20, 30, 40, 33, 24, 12, 5];//x轴的比例尺(创建一个序列化比例尺)var xScale = d3.scaleBand().domain(d3.range(dataset.length)).rangeRound([0, width - padding.left - padding.right]);var xAxis = d3.axisBottom(xScale); //定义x轴// y轴的比例尺var yScale = d3.scaleLinear().domain([0, d3.max(dataset)]).range([height - padding.top - padding.bottom, 0]);var yAxis = d3.axisLeft(yScale); //定义y轴//矩形之间的空白var rectPadding = 4;//添加矩形元素var rects = svg.selectAll(".MyRect").data(dataset).enter().append("rect").attr("class", "MyRect").attr("transform","translate(" + padding.left + "," + padding.top + ")").attr("x", function(d, i) {return xScale(i) + rectPadding / 2;}).attr("y", function(d) {return yScale(d);}).attr("width", xScale.step() - rectPadding).attr("height", function(d) {return height - padding.top - padding.bottom - yScale(d);}).attr("fill","blue");//添加文字元素var texts = svg.selectAll(".MyText").data(dataset).enter().append("text").attr("class", "MyText").attr("transform","translate(" + padding.left + "," + padding.top + ")").attr("x", function(d, i) {return xScale(i) + rectPadding / 2;}).attr("dx", function() {return (xScale.step() - rectPadding) / 2;}).attr("dy", function(d) {return 20;}).attr("fill","white").text(function(d) {return d;})// 先从底端出现.attr("y", function(d) {//return yScale(d);var min = yScale.domain()[0];return yScale(min);})// 开始动.transition().delay(function(d,i){return i * 200;}).duration(2000).ease(d3.easeBounce)// 最后跳到顶端.attr("y",function(d){return yScale(d);});//添加x轴svg.append("g").attr("class","axis").attr("transform","translate(" + padding.left + "," + (height - padding.bottom) + ")").call(xAxis); //添加y轴svg.append("g").attr("class","axis").attr("transform","translate(" + padding.left + "," + padding.top + ")").call(yAxis);</script>
交互式操作
有d3-brush(刷选,允许用户选择一个区域)、d3-zoom(缩放,允许用户用鼠标滚轮或手势缩放图表)、d3-drag(允许用户拖动元素,如节点、滑块等),还有一些鼠标和键盘事件可以用.on()
,第一个参数是监听的事件,第二个参数是一个函数,用来处理事件。
var circle = svg.append("circle");circle.on("click", function(){//在这里添加交互内容
});
鼠标常用的事件有:click、mouseover、mouseout、mousemove、mousedown、mouseup、dblclick(双击)。
键盘常用的事件有:keydown(按住不放触发、不区分大小写;keypress区分大小写)、keyup(释放键时触发,不区分字母大小写)
下面的实例创建一个柱状图,并实现以下交互功能:
- 悬停高亮:当鼠标悬停在柱子上时,柱子颜色改变。
- 点击切换:点击柱子时,柱子高度变化。
- 工具提示:悬停时显示工具提示,显示柱子的值。
- 缩放:允许用户通过鼠标滚轮缩放整个图表。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>D3.js 交互示例</title><script src="https://d3js.org/d3.v7.min.js"></script><style>.bar:hover {fill: orange; /* 悬停时柱子的颜色 */}.tooltip {position: absolute;background: white;padding: 5px;border: 1px solid #ccc;border-radius: 5px;pointer-events: none; /* 防止工具提示干扰鼠标事件 */}</style>
</head>
<body><div id="chart"></div><div class="tooltip" style="opacity: 0;"></div><script>// 数据const data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];// 定义画布尺寸和边距const width = 600;const height = 400;const margin = { top: 20, right: 20, bottom: 30, left: 40 };// 创建 SVG 画布const svg = d3.select("#chart").append("svg").attr("width", width).attr("height", height).call(d3.zoom().on("zoom", (event) => {svg.attr("transform", event.transform); // 缩放整个 SVG})).append("g").attr("transform", `translate(${margin.left}, ${margin.top})`);// 定义比例尺const xScale = d3.scaleBand().domain(data.map((d, i) => i)).range([0, width - margin.left - margin.right]).padding(0.1);const yScale = d3.scaleLinear().domain([0, d3.max(data)]).range([height - margin.top - margin.bottom, 0]);// 创建柱子svg.selectAll(".bar").data(data).enter().append("rect").attr("class", "bar").attr("x", (d, i) => xScale(i)).attr("y", d => yScale(d)).attr("width", xScale.bandwidth()).attr("height", d => height - margin.top - margin.bottom - yScale(d)).attr("fill", "steelblue").on("mouseover", function (event, d) {d3.select(this).attr("fill", "orange"); // 悬停时改变颜色tooltip.style("opacity", 1).html(`值: ${d}`).style("left", `${event.pageX + 5}px`).style("top", `${event.pageY - 20}px`);}).on("mouseout", function () {d3.select(this).attr("fill", "steelblue"); // 恢复颜色tooltip.style("opacity", 0);}).on("click", function (event, d) {const newHeight = d === 0 ? 100 : d / 2; // 点击时改变柱子高度d3.select(this).transition().duration(500).attr("y", yScale(newHeight)).attr("height", height - margin.top - margin.bottom - yScale(newHeight));});// 创建 X 轴svg.append("g").attr("transform", `translate(0, ${height - margin.top - margin.bottom})`).call(d3.axisBottom(xScale));// 创建 Y 轴svg.append("g").call(d3.axisLeft(yScale));// 工具提示const tooltip = d3.select(".tooltip");</script>
</body>
</html>