奇舞周刊
2021-02-19 15:22:47编者按:本文转载自 360企业安全可视化实验室 公众号,小心得系列,已获得公众号授权!
制作GIS可视化系统时,动画是绕不开的,因为动画能够更加生动的展示数据,增加信息。今天就给大家分享一下使用SVG作为动画载体,然后结合OpenLayers(后面简称OL)进行绘制。(为啥不用OL的API来实现动画,原因很简单:达成需求的成本太高)先上两张对比图(左侧OL API,右侧SVG)是不是右侧更加丝滑,更加好看:)
当然SVG本身也并不简单,那么我们来看看需要掌握哪些基础知识:
1、svg形状:
矩形
2、滤镜:
feGaussianBlur(高斯模糊)
feColorMatrix(矩阵转换)
3、渐变:
linearGradient(线性渐变)
radialGradient(放射性渐变)
4、svg animation元素:
今天我们重点讲两个案例,实例一扩散圆效果,实例二下坠攻击效果。这两个实例会使用:
1、形状:circle、path。
2、滤镜:feGaussianBlur(高斯模糊)。
3、渐变:radialGradient(放射渐变)、linearGradient(线性渐变)。
4、animation元素:animate和animateMotion。
代码如下:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="65" height="90" baseProfile="full">
<defs> <!-- 放射渐变 -->
<radialGradient id="radialGradient_r3" cx="50%" cy="50%" r="100%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:red;stop-opacity:0.2" />
<stop offset="50%" style="stop-color:red;stop-opacity:1" />
<stop offset="100%" style="stop-color:red;stop-opacity:0.2" />
</radialGradient>
</defs>
<circle cx="33" cy="60" r="6" stroke="black" stroke-width="0" fill="red" opacity="1" style="fill:url(#radialGradient_r3)"> </circle>
<circle cx="33" cy="60" r="0" stroke="black" stroke-width="0" fill="red" opacity="1" style="fill:url(#radialGradient_r3)">
<animate attributeName="r" attributeType="XML" begin="0s" dur="2s" from="1" to="25" repeatCount="indefinite" />
<animate attributeName="opacity" attributeType="CSS" begin="0s" dur="2s" from="1" to="0" repeatCount="indefinite"/>
</circle>
</svg>
可以存储为svg文件,即可作为图片文件引入使用,如下图所示,openlayers引入svg文件。
由于这个动画比较复杂,需要分步骤讲解:
代码如下:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="65" height="90" baseProfile="full">
<defs>
<!-- 放射渐变 -->
<radialGradient id="radialGradient_r3" cx="50%" cy="50%" r="100%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:red;stop-opacity:0.2" />
<stop offset="50%" style="stop-color:red;stop-opacity:1" />
<stop offset="100%" style="stop-color:red;stop-opacity:0.2" />
</radialGradient>
</defs>
<!-- 圆1 -->
<circle cx="33" cy="60" r="0" stroke="black" stroke-width="0" fill="red" opacity="1" style="fill:url(#radialGradient_r3)">
<animate attributeName="r" attributeType="XML" begin="0s" dur="2s" from="1" to="25" repeatCount="indefinite" />
<animate attributeName="opacity" attributeType="CSS" begin="0s" dur="2s" from="1" to="0" repeatCount="indefinite"/>
</circle>
<!-- 圆2 -->
<circle cx="33" cy="60" r="0" stroke="black" stroke-width="0" fill="red" opacity="1" style="fill:url(#radialGradient_r3)">
<animate attributeName="r" attributeType="XML" begin="1.5s" dur="2s" from="1" to="25" repeatCount="indefinite" />
<animate attributeName="opacity" attributeType="CSS" begin="1.5s" dur="2s" from="1" to="0" repeatCount="indefinite"/>
</circle>
</svg>
animate相关属性:
attributeName:设置过度属性。
begin:从0s开始(一般延时可以在这设置,第二个圆1.5s后开始)。
dur:持续时间,这里持续2s。
from:从n开始,这里圆半径从1开始。
to:到m结束,这里圆半径到25结束。
repeatCount:重复次数,indefinite表示无限重复,也可以设置指定次数。
放射性渐变定义方式:
SVG的
代码如下:
<g transform="translate(-480, -290)">
<!-- 内圈圆 -->
<circle cx="513" cy="350" r="22" style="fill:rgba(61,216,241,0);stroke:#6ae3eb;stroke-width:1">
</circle>
<!-- 中间圆 -->
<circle cx="513" cy="350" r="25" style="fill:rgba(61,241,218,0);stroke:rgba(61,216,241,1);stroke-width:1.5">
</circle>
<!-- 外部分瓣圆环 -->
<circle cx="513" cy="350" r="25" stroke-dasharray="25,28" style="fill:rgba(61,241,218,0);stroke:#00fee2;stroke-width:7">
<animateTransform attributeName="transform" begin="0s" dur="5s" type="rotate" from="0 513 350" to="360 513 350" repeatCount="indefinite" />
</circle>
</g>
animateMotion相关属性:
attributeName:同上。
begin:同上。
dur: 同上。
from:这里设置3个参数:旋转起始角度,圆心横坐标,圆心纵坐标。
to:这里设置3个参数:旋转结束角度,圆心横坐标,圆心纵坐标。
repeatCount:同上。
type:设置变换影响的参数,这里为rotate。
代码如下:
<defs>
<!-- 线性渐变 -->
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="103.5" y1="3" x2="103.5" y2="192.1667">
<stop offset="0" style="stop-color:rgba(205, 220, 57, 0.6);stop-opacity:0"/>
<stop offset="0.3" style="stop-color:rgba(205, 220, 57, 1);stop-opacity:1"/>
<stop offset="1" style="stop-color:rgba(205, 220, 57, 0.6);stop-opacity:0"/>
</linearGradient>
<!-- 定义高斯模糊滤镜 -->
<filter id="Gaussian_Blue">
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="5"/>
</filter>
</defs>
<!-- 光锥 -->
<g>
<polygon points="10,0 28,60 38,60 55,0" style="fill:url(#SVGID_2_);stroke:#000000; stroke-width:0;filter:url(#Gaussian_Blue)" />
</g>
放射性渐变定义方式:
请参考http://www.w3school.com.cn/svg/svg_grad_linear.asp,使用时在style中定义fill,url指向渐变的id即可。
高斯模糊滤镜定义方式:
请参考http://www.w3school.com.cn/svg/svg_filters_gaussian.asp,使用时在style中定义filter,url指向滤镜的id即可。
代码如下:
<defs>
<!-- 线性渐变 -->
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="103.5" y1="3" x2="103.5" y2="192.1667">
<stop offset="0" style="stop-color:#ccc"/>
<stop offset="0.6" style="stop-color:red;stop-opacity:0.6"/>
<stop offset="0.8839" style="stop-color:red;stop-opacity:0.2"/>
<stop offset="1" style="stop-color:red;stop-opacity:0"/>
</linearGradient>
</defs>
<!-- 小水滴1 -->
<g transform="translate(30, 0)" style="pointer-events: none;">
<path transform="rotate(180) scale(0.11)" fill="url(#SVGID_1_)" d="M126.8,192.2C142.4,172.5,160,143,160,110c0-59.1-56.5-107-56.5-107S47,50.9,47,110
c0,33,17.6,62.5,33.2,82.2C92.5,176.7,114.5,176.7,126.8,192.2z"/>
<animateMotion path="M15 0 L15 60" begin="0s" dur="0.8s" repeatCount="indefinite"/>
</g>
代码如下:
<!-- 小水滴2 -->
<g transform="translate(30, -30)" style="pointer-events: none;">
<path transform="rotate(180) scale(0.11)" fill="url(#SVGID_1_)" d="M126.8,192.2C142.4,172.5,160,143,160,110c0-59.1-56.5-107-56.5-107S47,50.9,47,110
c0,33,17.6,62.5,33.2,82.2C92.5,176.7,114.5,176.7,126.8,192.2z"/>
<animateMotion path="M15 0 L15 90" begin="0.2s" dur="0.8s" repeatCount="indefinite"/>
</g>
是不是意犹未尽?跃跃欲试?
完整代码示例请戳:
https://codepen.io/zxm/pen/EExGLJ?editors=0010
《奇舞周刊》是360公司专业前端团队「奇舞团」运营的前端技术社区。关注公众号后,直接发送链接到后台即可给我们投稿。