一根飞线的故事-SVG篇

本文详细介绍了如何使用SVG的PathElement来创建飞线动效。通过SVGPathElement.getTotalLength和SVGPathElement.getPointAtLength方法获取路径长度和坐标点,结合D3库实现飞线的动态绘制。文章还探讨了性能优化,如利用贝塞尔曲线和过渡效果减少元素数量,以及使用SVG滤镜提升视觉效果。
摘要由CSDN通过智能技术生成

作者|数澜UED团队

没有飞线的地图就像一个发际线上移的中年人一样平淡无奇。 —— By 胖子

每年春运和双十一的统计图都因为有飞线动效才更加吸引眼球,今天要为大家带来一根漂亮飞线要用什么姿势生成才能。

SVG

本篇是主讲SVG来绘制飞线的,所以强大的SVG必定能完成我们绘制飞线效果的各种需求。首先我先为各位介绍下完成这根线需要用到的一些小知识点。

Path元素

path元素
是SVG基本形状中最强大的一个,它不仅能创建其他基本形状,还能创建更多其他形状。这里我们只需要用它来绘制一条曲线。

首先我们先创建好这根曲(tou)线(fa)。

OK,这根头发我们已经在屏幕上放好了,如果你将path元素的曲线无限放大会发现,其实它是由非常多的坐标点相互连接组成的。这个时候脑洞放一下,如果我们能获取到这些点是不是就是获取了线的绘制轨迹。就可以逐帧绘制飞线了动效了。


那要如何来获取和使用这些坐标点呢?

勤奋的查阅MDN,我发现这个问题强大的SVG已经帮我们解决了,可以使用getTotalLengthgetPointAtLength这两个方法来搞定。

[SVGPathElement.getTotalLength](https://developer.mozilla.org/en-US/docs/Web/API/SVGPathElement/getTotalLength

但因为SVG中绘制的都是矢量图,所以path元素不存在是由若干个点构成的,所以调用该方法会返回该path元素从起始点到终点的总长度(浮点数)。

尽管和预期有所差别,但搭配上下面的getPointAtLength方法我们依然能完成之前预想的实现方法。

SVGPathElement.getPointAtLength

调用该方法会根据传入到起点的距离值来计算返回对应的path元素坐标点的位置x、y值。

通过组合使用这两方法,我们可以自己定义这段轨迹上有有多少个坐标点,并且可以获取对应这些点的坐标值。

下面我们使用D3来操作这些DOM节点获取对应的节点数据信息

首先我们需要先定义好飞线轨迹是由多少个点构成的:

const pointNum = 1500

接下来我们可以通过方法将获取到的轨迹总长度进行平分得到单位长度unit,然后再调用getPointAtLength获取对应距离的坐标值。

const pointNum = 1500
const path = d3.select('#line')
const pathline = path.node()
const totalLength = pathline.getTotalLength()
const points = []

const unit = totalLength / pointNum

for (let i = 0; i <= pointNum; i += 1) {
   
  points.push(pathline.getPointAtLength(i * unit))
}

接下来我们就可以通过这些数据绘制飞线动效了!

接下来我们就可以通过这些数据绘制飞线动效了!

接下来我们就可以通过这些数据绘制飞线动效了!

重要的话我们来强调三遍。

飞线动效-1

如下图,其实实现飞线具体头部深、尾部浅效果可以通过绘制若干透明度逐渐递减的圆来达到。(Echarts飞线使用类似思路)

接下来所需要做的就是让上面的飞线像下图的矩形一样,让它按照对应的轨迹路线来进行移动。

但由于飞线是由若干个圆重叠组成的,所以不能像矩形一样只需要控制一个元素的xy值就搞定运动行为。尤其是如下图这样的曲线运动的情况。

为此我们需要声明一个飞线类,首先需要定义飞线的长度、样式速度等特性。

由于之前已经声明好该路径轨迹拆分成多少段了,所以在此我们取个巧定义飞线的长度是其中lineLen段的长度,设定速度为每次渲染移动speed段。

class FlyLine {
   
  totalNum = 1500
  lineLen = 150
  speed = 15
  radius = 2.5
  fill = 'rgb(255, 200, 65)'
  circles = []
  constructor(){
   
    // percent的用处会在后面体现
    this.percent = this.lineLen
  }
}

上面的说明看不懂?灵魂画手图片解析

定义好飞线的特性变量之后&#x

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值