如何实现D3中rect元素从中心缩放的动画效果?
让D3中的rect元素从中心点缩放动画的解决方案
嘿,这个问题我之前做可视化的时候也踩过坑!默认情况下D3修改rect的width/height属性时,确实是从左上角开始拉伸或缩小的,要实现从中心点向四周扩展/收缩的动画,核心思路就是同步调整rect的x和y坐标——毕竟rect的定位是基于左上角的,缩放时得把坐标往反方向挪一半的尺寸变化量,才能保证中心位置不变。
下面给你调整后的代码思路,结合你的现有代码修改:
方法一:如果数据中已存储初始坐标和尺寸
假设你的每个.anchor元素对应的数据对象d里已经有初始的x、y、width、height,以及目标的宽高(比如targetWidth、targetHeight),可以直接这样写:
.selectAll(".anchor") .transition() .duration(800) .delay(function (d, i) { return i * 50; }) .attr("fill", _graphics.colors.red) // 关键:同步更新x、y坐标,抵消宽高变化带来的偏移 .attr("x", function(d) { // 新x = 初始x - (目标宽度 - 初始宽度)/2 return d.x - (d.targetWidth - d.width)/2; }) .attr("y", function(d) { // 新y = 初始y - (目标高度 - 初始高度)/2 return d.y - (d.targetHeight - d.height)/2; }) .attr("width", function(d) { return d.targetWidth; }) .attr("height", function(d) { return d.targetHeight; }) .attr("rx", targetRx) // 圆角属性同理,按需修改 .attr("ry", targetRy);
方法二:如果没有存储初始值,先获取当前元素属性
如果你的数据里没提前存初始尺寸和坐标,可以在动画开始前先获取每个rect的当前属性,存到数据对象里再计算:
.selectAll(".anchor") // 先把当前元素的属性存到数据d里 .each(function(d) { d.currentX = +d3.select(this).attr("x"); d.currentY = +d3.select(this).attr("y"); d.currentWidth = +d3.select(this).attr("width"); d.currentHeight = +d3.select(this).attr("height"); }) .transition() .duration(800) .delay(function (d, i) { return i * 50; }) .attr("fill", _graphics.colors.red) .attr("x", function(d) { // 这里假设你已经定义了目标宽高,比如newWidth、newHeight return d.currentX - (newWidth - d.currentWidth)/2; }) .attr("y", function(d) { return d.currentY - (newHeight - d.currentHeight)/2; }) .attr("width", newWidth) .attr("height", newHeight) .attr("rx", newRx) .attr("ry", newRy);
原理说明
rect的x和y属性控制的是它左上角的位置,当宽度增加时,要让中心不变,就得把x往左移动一半的宽度增量;高度增加时,把y往上移动一半的高度增量。如果是缩小的情况,增量是负数,x和y会自动往相反方向调整,同样能保持中心位置固定。
这样修改后,你的rect动画就会从中心点向四周平滑缩放啦!
内容的提问来源于stack exchange,提问作者PFlans
相关产品推荐
相关产品推荐

