国产动画音乐分享组

SVG动画在OL中的丝滑体验

奇舞周刊 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元素:

延时改变某个属性值

单属性的动画过渡效果

transform变换动画效果

路径动画效果

今天我们重点讲两个案例,实例一扩散圆效果,实例二下坠攻击效果。这两个实例会使用:

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文件。

实例二:下坠攻击效果

由于这个动画比较复杂,需要分步骤讲解:

1、绘制同圆心两个扩散圆

代码如下:

<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的元素用于预定义一个元素使其能够在SVG图像中重复使用,滤镜一般定义在 这里。请参考http://www.w3school.com.cn/svg/svg_grad_radial.asp,radialGradient标签使用必需的 id 属性来定义向图形应用哪个渐变,使用时在style中定义fill,url指向渐变的id即可。

2、绘制外圈旋转圆环

代码如下:

<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。

3、绘制光锥效果

代码如下:

<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即可。

高斯模糊滤镜定义方式:

标签用来定义 SVG 滤镜。标签使用必需的 id 属性来定义向图形应用哪个滤镜,标签必须嵌套在标签内。

请参考http://www.w3school.com.cn/svg/svg_filters_gaussian.asp,使用时在style中定义filter,url指向滤镜的id即可。

4、绘制水滴坠落效果

代码如下:

<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>

5、绘制第二个小水滴

代码如下:

<!-- 小水滴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公司专业前端团队「奇舞团」运营的前端技术社区。关注公众号后,直接发送链接到后台即可给我们投稿。


Copyright © 国产动画音乐分享组@2017