最近打算给我手写的可视化编辑器的拓扑图的连线加个动画效果,因为市场那边说没动画,没那么好忽悠客户,安排!!!一开始加了虚线滑动的形式发现真坤儿丑!而且平平无奇。后面用渐变的实现方式还挺好看的,所以记录一下。
各位爷先看效果:
原理:
一个渐变,然后移动渐变。简单吧!!!首先学如下两个标签。后面我用demo附上源码详细讲讲
<linearGradient>(这个就是渐变)
定义一个线性颜色渐变。线性渐变会沿着一条直线在不同的颜色之间进行平滑过渡。
由以下几部分组成:
-
<linearGradient>标签本身: 定义渐变的容器。 -
id属性: 必不可少,用于在其他元素中引用这个渐变。 -
x1,y1,x2,y2属性: 定义渐变的起始点和结束点,决定了渐变的方向。 -
<stop>子标签: 定义渐变中的颜色停止点。属性 描述 必填/可选 示例值 offset 颜色停止点的位置。一个 0 到 1 之间的数字(表示百分比),或一个百分比字符串(例如 0% 到 100%)。 0 或 0% 表示渐变线的起始点,1 或 100% 表示结束点。 必填 0, 0.5, 1, 25%, 75% stop-color 停止点的颜色。任何有效的 CSS 颜色值。 必填 red, #FF0000, rgb(255, 0, 0) stop-opacity 停止点的不透明度。一个 0 到 1 之间的数字。默认值是 1 (完全不透明)。 可选 0, 0.5, 1 -
gradientUnits:坐标的单位类型,默认为
objectBoundingBox(相对于图形大小),可设为userSpaceOnUse(绝对坐标)。
<animateTransform>(这个就是用来移动渐变)
用于处理 形变动画 的元素,支持对图形或渐变进行平移、旋转、缩放、倾斜等变换操作。
| 属性 | 描述 |
|---|---|
attributeName | transform,动画图形元素的变换。gradientTransform, 渐变本身的变换 |
type | 变换类型,可选值:translate、scale、rotate、skewX、skewY。 |
from | 起始值(例如 0 0 表示平移起点)。 |
to | 结束值(例如 100 100 表示平移终点)。 |
dur | 动画持续时间(单位:秒)。 |
repeatCount | 动画重复次数(indefinite 表示无限循环)。 |
begin | 动画开始时间(支持时间值或事件触发,如 click)。 |
还有个属性是values,就是定义多个关键帧的。跟from和to的功能一样,只不过from和to表示两个关键帧也就是开始和结束。
demo效果:
源码(vue复制即可运行):
<template>
<div class="container">
<svg ref="svgCanvas" class="svg-canvas" :width="1920" :height="800">
<!-- 定义区:存放渐变、滤镜等可复用的元素 -->
<defs>
<!-- 线性渐变 -->
<linearGradient
id="currentGradient"
gradientUnits="userSpaceOnUse"
x1="50"
y1="50"
x2="550"
y2="100"
>
<!-- 0%位置:完全透明 -->
<stop offset="0%" stop-color="transparent" />
<!-- 20%位置:完全透明 -->
<stop offset="20%" stop-color="transparent" />
<!-- 35%位置:淡红色 -->
<stop offset="35%" stop-color="red" stop-opacity="0.2" />
<!-- 45%位置:中等红色 -->
<stop offset="45%" stop-color="red" stop-opacity="0.6" />
<!-- 50%位置:最亮红色(电流中心) -->
<stop offset="50%" stop-color="red" stop-opacity="1" />
<!-- 55%位置:中等红色 -->
<stop offset="55%" stop-color="red" stop-opacity="0.6" />
<!-- 65%位置:淡红色 -->
<stop offset="65%" stop-color="red" stop-opacity="0.2" />
<!-- 80%位置:完全透明 -->
<stop offset="80%" stop-color="transparent" />
<!-- 100%位置:完全透明 -->
<stop offset="100%" stop-color="transparent" />
<!-- 动画变换:让渐变移动产生电流流动效果 -->
<animateTransform
attributeName="gradientTransform"
type="translate"
values="-500 0; 500 0"
dur="2s"
repeatCount="indefinite"
/>
</linearGradient>
</defs>
<!-- 背景路径:背景板,没这玩意也行,主要是突出效果 -->
<polyline
points="50,50 550,50"
fill="none"
stroke="#333333"
stroke-width="10"
></polyline>
<!-- 渐变路径:这个就是渐变的路径 -->
<polyline
points="50,50 550,50"
fill="none"
stroke="url(#currentGradient)"
stroke-width="8"
></polyline>
</svg>
</div>
</template>
流程:
(1)定义个一个渐变linearGradient,x,y是初始位置,也是渐变的初始方向,xy的值一般是被引用路径的起点和结束点,如polyline的points所展示的点。
(2)然后子元素定义一个animateTransform控制渐变的位移变换,values 定义了 渐变坐标系的整体平移方向, values值”;“号为一组,前为x后为y,作用是位移,比如渐变的水平方向的长度现在是dx(550 - 50),那我就-500往左位移这样渐变在起始帧就是隐藏的,结束帧为500,那么这个过程就是移动渐变-500到500的过程。
(3)stroke="url(#currentGradient)"路径引用渐变
延伸:
假设如上源码,points的值改为"50,50 180,100, 250,190 550,50",animateTransform的values是否需要跟polyline的 points对应, 如每一段都有对应的values值对应?
答案:不需要, 只要 渐变的移动方向 与 路径的整体延伸方向 一致,动画效果就会自然覆盖整个路径,无需逐段匹配。
animateTransform 作用的是渐变本身,不是路径
values="-500 0; 500 0"是在移动整个渐变- 渐变是一个独立的"颜色分布系统"
就相当于stroke="url(#currentGradient)"引用渐变时,告诉svg你用这个渐变描绘我的路径。SVG 渲染器会把当前时间点上,渐变所处的那个位置和状态下的图案,映射并拉伸到你的 polyline 路径的整个长度上。