d3实现字符跳动效果
本文的示例之前出现在 d3 官方 demo 中,这里对它重新实现一遍,你可以点击这里查看最终效果。
主要实现效果
- 进入时,字符为绿色,从上方 50 像素的位置,由透明变为不透明偏移进入。
- 进入后,插入到正确位置,原来字符需要移动的,就偏移到正确位置,更新的字符颜色变为
#ccc
。 - 下一次更新时,不存在的节点直接删除,删除时字符变为红色,并向下偏移 50 像素变为透明移除。
实现
首先需要创建一组字符,并将字符显示到页面中。
const text = svg.selectAll('text').data(data, (d) => d);
text
.enter()
.append('text')
.attr('y', 50)
.style('font-size', 18)
.attr('fill', '#ccc')
.attr('x', (d, i) => i * 32)
.text((d) => d);
此时页面中将会存在一组静态的字符。
接下来,就要让字符动起来,使用interval
定时重复执行渲染。
这里每次都将字符的顺序打乱进行渲染。
d3.interval(() => {
update(
d3
.shuffle(words)
.slice(0, Math.floor(Math.random() * 26))
.sort(),
);
}, 2000);
你会发现,字符并没有任何变化,这是因为还没有写更新相关的代码。
// 加上更新代码
text.attr('x', (d, i) => i * 32);
又出问题了,好多字符都重叠在一起。这是因为在每一次更新时还保留了上一次的内容,所以导致了字符覆盖。因此,在每一次插入之前,我们需要将不存在的字符节点删除。
text.exit().remove();
这下页面正常了。不知道你是否发现,上述代码的处理进入时和更新时其实有一部分逻辑是一样的,为了减少这部分一样的逻辑,d3 提供了一个merge
方法。
text
.enter()
.append('text')
.attr('y', 50)
.style('font-size', 18)
.attr('fill', '#ccc')
.text((d) => d)
.merge(text)
// 之前enter部分的逻辑可以挪动到merge之后,表示处理enter和update
.attr('x', (d, i) => i * 32);
虽然实现的字符变化的效果,但是变化的过程十分生硬,我们可以通过 transition
给它加上动画。
使用 transition
,可以控制位置、颜色等等样式进行动画过渡。
text.attr('x', 10).style('fill', '#f00').transition().duration(500).attr('x', 20).attr('fill', '#0f0');
上面这段代码可以简单地实现在 500 毫秒中,坐标从 10 过渡到 20,颜色从红色过渡为绿色。
那么,对于字符的动画处理也是如此。
const t = d3.transition().duration(750);
text
.enter()
.append('text')
.style('fill-opacity', 1e-6)
.attr('dy', -50)
// 设置过渡
.transition(t)
.attr('dy', 0)
.style('fill-opacity', 1);
最终实现的效果可以参见字符跳动效果
如果您觉得本文对您有用,欢迎捐赠或留言~
- 本博客所有文章除特别声明外,均可转载和分享,转载请注明出处!
- 本文地址:https://www.leevii.com/?p=3045