svg和canvas及CSS3动画初探

Author Avatar
zongyuan 7月 05, 2018 【字数:3,594】 【阅读时长:14min】
  • 在其它设备中阅读本文章
  • 前端动画初探…

    动画

    补间动画 【查看demo】

    所谓补间动画又叫做中间帧动画,渐变动画,只要建立起始和结束的画面,中间部分由软件自动生成,省去了中间动画制作的复杂过程

    常见的实现补间动画以下几种形式:

    • CSS3 animation,通过animation(除steps()以外的时间函数)属性在每个关键帧之间插入补间动画。了解一下
    • CSS3 transition,区别于animationtransition只能设定初始和结束时刻的两个关键帧状态。
      transition的优点在于简单易用,但是它有几个很大的局限。
      • (1)transition需要事件触发,所以没法在网页加载时自动发生。
      • (2)transition是一次性的,不能重复发生,除非一再触发。
      • (3)transition只能定义开始状态和结束状态,不能定义中间状态,也就是说只有两个状态。
      • (4)一条transition规则,只能定义一个属性的变化,不能涉及多个属性。
    • SVG 动画,考虑到高版本现代浏览器对SVG技术的友好的支持性,利用SVG技术实现动画也是一种可行的方案。了解一下
      tips:动画要自然不生硬,【十二法则】了解一下
    逐帧动画

    定格动画,又名逐帧动画,是一种动画技术,其原理即将每帧不同的图像连续播放,从而产生动画效果。

    • 两个条件:(1)相关联的不同图像,即动画帧;(2)连续播放。
    • 三种技术(视频可以实现所有类型的动画,暂不纳入):gifJavaScriptCSS3 animation
      一、gif
      • 优点:成本较低、使用方便。
      • 缺点:
        画质上,gif 支持颜色少(最大256色)、Alpha 透明度支持差,图像锯齿毛边比较严重;
        交互上,不能直接控制播放、暂停、播放次数,灵活性差;
        性能上,gif 会引起页面周期性的 paint ,性能较差。
        在触屏页中,gif 常被用来做加载动画。如《陌陌不孤独饭局》的加载动画:
        gif动画示例
        二、JS
      • JSCSS3,一般是将动画帧放到背景图中。不同的是, JS是使用脚本来控制动画的连续播放的:可以直接改变元素的 background-image【序列图片视频化-查看demo】,也可以将动画帧合并成雪碧图,通过改变 background-position 来实现(即不同帧数用不同class的加载图片,使用 JS 改变样式名:)
      • 将动画帧合并成雪碧图,通过改变 background-position 来实现,CSS3 实际上是使用 animation-timing-function 的阶梯函数 steps(number_of_steps, direction)【查看demo】 来实现逐帧动画的连续播放的。
      • 在移动端,CSS3 animation 兼容性良好,相对于 JSCSS3 逐帧动画使用简单,且效率更高,因为许多优化都在浏览器底层完成。
      • CSS3 animation属性中的steps功能符深入介绍
    3D动画【查看demo】
    • 3D变换相较2D变换,坐标系中多了Z轴,也就意味着物体除了上下左右,还可以前后移动。而 rotate在2D中的旋转方式,在3D中与 rotateZ相当。
    • CSS3中的perspective了解一下在这样一个体系里就代表着元素与观者之间的距离,形象点说,就是元素3D效果的强度。CSS3中的3D效果消失点固定,变化的是观者与元素之间的距离。不过perspective数值与3D效果强度是成反比的,数值越大,元素的3D效果越不明显——2000px的视点意味着你看的是远方的物体,而100px则意味着这个物体就在你眼前【查看demo】
    • 将3D效果数量控制在一定范围内,页面性能才是重中之重
    动画性能

    避免为开销大的属性设置动画,要让每次在设置动画时必须注意保持 60fps

    • 12 fps:由于人类眼睛的特殊生理结构,如果所看画面之帧率高于每秒约10-12帧的时候,就会认为是连贯的
    • 24 fps:有声电影的拍摄及播放帧率均为每秒24帧,对一般人而言已算可接受
    • 30 fps:早期的高动态电子游戏,帧率少于每秒30帧的话就会显得不连贯,这是因为没有动态模糊使流畅度降低
    • 60 fps:在实际体验中,60帧相对于30帧有着更好的体验
    • 85 fps:一般而言,大脑处理视频的极限

      页面渲染的一般过程为JS > CSS > 计算样式 > 重排 > 重绘 > 渲染层合并。

      其中,Layout(重排)和Paint(重绘)是整个环节中最为耗时的两环,所以我们尽量避免这两个环节。从性能方面考虑,最理想的渲染流水线是没有布局和绘制环节的,只需要做渲染层的合并即可。

      在实际的应用里,最为简单的一个注意点就是,触发动画的开始不要用diaplay:none属性值,因为它会引起LayoutPaint环节,通过切换类名就是一种很好的办法。

    简介

    svg
    • 指可缩放矢量图形是基于可扩展标记语言(标准通用标记语言的子集),用于描述二维矢量图形的一种图形格式。
      在 2003 年一月,SVG 1.1 被确立为 W3C 标准。
    canvas
    • 指在HTML5中新增的标签用于在网页实时生成图像,并且可以操作图像内容,基本上它是一个可以用JavaScript操作的位图(bitmap)。
      2014年10月29日,万维网联盟宣布,经过接近8年的艰苦努力,该标准规范终于制定完成。

    能做什么?

    svg 【查看demo】
    • SVG 文件可以直接插入网页,成为 DOM 的一部分,然后用 JavaScriptCSS 进行操作。
      <svg width="200" height="200">
          <rect x="50" y="25" width="100" height="50" fill="#4284ed"></rect>
      </svg>
      
    • SVG 代码也可以写在一个独立文件中,然后用<img><object><embed><iframe>等标签插入网页。
      <img src="circle.svg">
      <object id="object" data="circle.svg" type="image/svg+xml"></object>
      <embed id="embed" src="icon.svg" type="image/svg+xml">
      <iframe id="iframe" src="icon.svg"></iframe>
      
    • CSS 也可以使用 SVG 文件。
      background: url(icon.svg);
      
    • SVG 文件还可以转为 BASE64 编码,然后作为 Data URI 写入网页。

      <img src="data:image/svg+xml;base64,[data]">
      
    • snap 了解一下

    矩形 <rect>

    • x 属性定义矩形的左侧位置(例如,x=”0” 定义矩形到浏览器窗口左侧的距离是 0px)
    • y 属性定义矩形的顶端位置(例如,y=”0” 定义矩形到浏览器窗口顶端的距离是 0px)
      <svg width="200" height="200">
          <rect x="50" y="25" width="100" height="50" fill="#4284ed"></rect>
          <rect x="50" y="125" width="100" height="50" stroke="#4284ed" stroke-width="2" fill="none"></rect>
      </svg>
      

    圆形 <circle>

    • cx和cy属性定义圆点的x和y坐标。如果省略cx和cy,圆的中心会被设置为(0, 0)
    • r属性定义圆的半径
      <circle cx="100" cy="50" r="40" fill="#4284ed"></circle>
      

    椭圆 <ellipse>

    • rx属性定义的水平半径
    • ry属性定义的垂直半径
      <ellipse cx="100" cy="50" rx="50" ry="20" fill="#4284ed"></ellipse>
      

    线 <line>

    • x1 属性在 x 轴定义线条的开始
    • y1 属性在 y 轴定义线条的开始
    • x2 属性在 x 轴定义线条的结束
    • y2 属性在 y 轴定义线条的结束
      <line x1="20" y1="30" x2="180" y2="30" stroke="#4284ed" stroke-width="10" stroke-linecap="butt"></line>
      

    折线 <polyline>(不闭合)

    • points 属性定义折线每个点的 x 和 y 坐标
      <polyline points="20 20 20 80 80 80 100 100 180 100 180 180" stroke="#4284ed" stroke-width="4" fill="none"></polyline>
      

    多边形 <polygon>(闭合)

    • points 属性定义多边形每个角的 x 和 y 坐标
      <polygon points="50 50 150 10 150 90" fill="#4284ed"></polygon>
      

    路径 <path>

    • M = moveto
    • L = lineto
    • H = horizontal lineto
    • V = vertical lineto
    • C = curveto
    • S = smooth curveto
    • Q = quadratic Bézier curve
    • T = smooth quadratic Bézier curveto
    • A = elliptical Arc
    • Z = closepath
      <path d="M10 10 C 20 20, 40 20, 50 10" stroke="#4284ed" fill="none" />
      

    图片 <image>

    • x=”图像的左上角的x轴坐标”
    • y=”图像的左上角的y轴坐标”
    • width=”图像的宽度”. 必须.
    • height=”图像的高度”. 必须.
    • xlink:href=”图像的路径”. 必须.
      <image x="0" y="0" width="200" height="200" xlink:href="../imgs/dota-2.png"></image>
      

    文本<text>

    • x=”文字的左上角的x轴坐标”
    • y=”文字的左上角的y轴坐标”
      <text x="50" y="80" fill="#4284ed" style="font-size: 30px;">这是文字</text>
      

    样式<标签属性>

    • stroke(轮廓的颜色)
    • stroke-width(轮廓的宽度)
    • stroke-linecap(轮廓的两端的样式)
    • stroke-dasharray(创建轮廓虚线)
    • fill(填充的颜色)

    样式

    • style 属性用来定义 CSS 属性
    • CSS 的 fill 属性定义矩形的填充颜色(rgb 值、颜色名或者十六进制值)
    • CSS 的 fill-opacity 属性定义填充颜色透明度(合法的范围是:0 - 1)
    • CSS 的 stroke-opacity 属性定义轮廓颜色的透明度(合法的范围是:0 - 1)
    canvas【查看demo】

    创建画布

    <canvas id="canvas" width="200" height="100">您的浏览器不支持 HTML5 canvas 标签。</canvas>
    

    js初始化

    let c=document.getElementById("canvas");
    let ctx=c.getContext("2d");
    

    在使用canvas前,用canvas.getContext来测试浏览器是否支持canvas

    if (canvas.getContext) {
        console.log('你的浏览器支持canvas!');
    } else {
        console.log('你的浏览器不支持canvas!');
    }
    

    canvas坐标

    • canvas 是一个二维网格。
    • canvas 的左上角坐标为 (0,0)

    canvas坐标系

    canvas - 矩形

    • rect(x,y,width,height);
    • stroke() 或者 fill()

    canvas - 圆

    • beginPath()
    • arc(x,y,r,start,stop)
    • stroke()

    canvas - 线条

    • moveTo(x,y) 定义线条开始坐标
    • lineTo(x,y) 定义线条结束坐标
    • 然后使用 stroke() 方法来绘制线条

    canvas - 文本

    • font - 定义字体
    • fillText(text,x,y) - 在 canvas 上绘制实心的文本
    • strokeText(text,x,y) - 在 canvas 上绘制空心的文本

    canvas - 图像【查看demo】

    • drawImage(image,x,y)

    canvas模糊解决方法,将画布尺寸设为显示尺寸的2倍

    canvas.setAttribute('width', x * 2);
    canvas.setAttribute('height', y * 2);
    canvas.style.width = x + 'px';
    canvas.style.height = y + 'px';
    

    优缺点

    svg
    • 不依赖分辨率
    • 支持事件处理器
    • 最适合带有大型渲染区域的应用程序(比如谷歌地图)
    • 复杂度高会减慢渲染速度(任何过度使用 DOM 的应用都不快)
    • 不适合游戏应用
    • 生成的是矢量图。

    SVG的本质特征,或者称为立世之本就是矢量可缩放(如论如何缩放,图像边缘都是平滑的)

    canvas
    • 依赖分辨率
    • 不支持事件处理器
    • 弱的文本渲染能力
    • 能够以 .png.jpg 格式保存结果图像
    • 最适合图像密集型的游戏,其中的许多对象会被频繁重绘
    • 生成的是标量图。

    制作动画的几个基本要求【查看demo】

    • 各种方式的(svg,canvas,CSS3)动效原理
      比如canvas就是不断清除画布再绘制,清除再绘制,js,CSS3的浏览器引起的重排重绘等

    • JS基本功
      js的复杂度肯定会随着动画的复杂度提升。例如,了解实例对象的属性如何获取,以及上下文this指代什么;如何有效地遍历以及数据存储等等。

    • 动画相关API
      canvas,svg绘制线条,绘制圆,绘制不规则图形;如何描边,如何填充,如何控制透明度等等。
      CSS3 animation transition 各参数含义等。

      CSS3 animation

      animation: name duration timing-function delay iteration-count direction fill-mode play-state;
      
      • animation-name 指定要绑定到选择器的关键帧的名称
      • animation-duration 动画指定需要多少秒或毫秒完成 负值
      • animation-timing-function 设置动画将如何完成一个周期 linear ease cubic-bezier(n,n,n,n)
      • animation-delay 设置动画在启动前的延迟间隔。
      • animation-iteration-count 定义动画的播放次数。
      • animation-direction 指定是否应该轮流反向播放动画。normal alternate
      • animation-fill-mode 规定当动画不播放时(当动画完成时,或当动画有一个延迟未开始播放时),要应用到元素的样式。 forwards backwards both
      • animation-play-state 指定动画是否正在运行或已暂停。 running paused

        要和关键帧keyframes结合使用

        keyframes name {
            from{}
            to{}
        }
        

        CSS3 transition

        transition: property duration timing-function delay;
        
      • transition-property 规定设置过渡效果的 CSS 属性的名称,列表以逗号分隔。
      • transition-duration 规定完成过渡效果需要多少秒或毫秒。
      • transition-timing-function 规定速度效果的速度曲线。
      • transition-delay 定义过渡效果何时开始。

        SVG animate

        <animate
        attributeName="width"
        attributeType="XML"
        from="200" to="20"
        begin="0s" dur="5s"
        repeatDur="10" repeatCount="2"
        fill="freeze" />
        
      • attributeName 定义发生变化的元素属性名
      • attributeType XML CSS
      • from&to&by fromto分别定义发生变化的属性的初始值和终止值。from可缺省,表示初始值即为<animate>父元素相应的属性值。可用by替换to,表示变化偏移量。可以理解为to = from + by
      • begin & dur & end begin定义动画开始时间;dur定义动画所需时间;end定义动画终止时间。时间单位h:小时;min:分钟;s:秒;ms:毫秒。默认时间单位为s
      • fillfill="freeze"时,动画终止时,发生变化的元素属性值停留在动画终止时的状态;当fill="remove"时,动画终止时,发生变化的元素属性值回复到动画起始时的状态。
    • 常见的曲线函数【查看demo】
      通常而言,常见的图形绘制,或者运动轨迹之类,都是需要借助数学函数的。也就是要有一定的数学功力,无论是CSS3 transform变幻还是我们平时所见的各种动画效果,其本质上都是数学函数运动和矩阵变换,因此,要想再图形可视化以及视觉动效领域有所建树,数学不能差。
      了解下贝塞尔曲线cubic-bezier(<x1>, <y1>, <x2>, <y2>)了解一下,如CSS3 animation transition 的速度曲线函数。

    应用

    svg
    canvas

    总结

    考虑到兼容性的问题,在项目实践中,一般我们在桌面浏览器端任然推荐使用JavaScript直接实现动画的方式或SVG动画的实现方式,移动端则可以考虑使用CSS3canvasrequestanimationFrame

    感谢阅读 thx~
    本文链接:https://627235655.github.io/2018/07/05/svg-and-canvas/