svg和canvas及CSS3动画初探
动画
补间动画 【查看demo】
所谓补间动画又叫做中间帧动画,渐变动画,只要建立起始和结束的画面,中间部分由软件自动生成,省去了中间动画制作的复杂过程
常见的实现补间动画以下几种形式:
CSS3 animation
,通过animation
(除steps()以外的时间函数)属性在每个关键帧之间插入补间动画。了解一下CSS3 transition
,区别于animation
,transition
只能设定初始和结束时刻的两个关键帧状态。
transition
的优点在于简单易用,但是它有几个很大的局限。- (1)
transition
需要事件触发,所以没法在网页加载时自动发生。 - (2)
transition
是一次性的,不能重复发生,除非一再触发。 - (3)
transition
只能定义开始状态和结束状态,不能定义中间状态,也就是说只有两个状态。 - (4)一条
transition
规则,只能定义一个属性的变化,不能涉及多个属性。
- (1)
- SVG 动画,考虑到高版本现代浏览器对SVG技术的友好的支持性,利用SVG技术实现动画也是一种可行的方案。了解一下
tips:动画要自然不生硬,【十二法则】了解一下
逐帧动画
定格动画,又名逐帧动画,是一种动画技术,其原理即将每帧不同的图像连续播放,从而产生动画效果。
- 两个条件:(1)相关联的不同图像,即动画帧;(2)连续播放。
- 三种技术(视频可以实现所有类型的动画,暂不纳入):
gif
、JavaScript
、CSS3 animation
一、gif
- 优点:成本较低、使用方便。
- 缺点:
画质上,gif
支持颜色少(最大256色)、Alpha 透明度支持差,图像锯齿毛边比较严重;
交互上,不能直接控制播放、暂停、播放次数,灵活性差;
性能上,gif
会引起页面周期性的 paint ,性能较差。
在触屏页中,gif
常被用来做加载动画。如《陌陌不孤独饭局》的加载动画:二、JS
JS
与CSS3
,一般是将动画帧放到背景图中。不同的是,JS
是使用脚本来控制动画的连续播放的:可以直接改变元素的background-image
【序列图片视频化-查看demo】,也可以将动画帧合并成雪碧图,通过改变background-position
来实现(即不同帧数用不同class
的加载图片,使用JS
改变样式名:)
- 优点:兼容性佳,交互灵活。
三、CSS3 animation【查看demo】
- 将动画帧合并成雪碧图,通过改变
background-position
来实现,CSS3 实际上是使用animation-timing-function
的阶梯函数steps(number_of_steps, direction)
【查看demo】 来实现逐帧动画的连续播放的。 - 在移动端,
CSS3 animation
兼容性良好,相对于JS
,CSS3
逐帧动画使用简单,且效率更高,因为许多优化都在浏览器底层完成。 - 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
属性值,因为它会引起Layout
、Paint
环节,通过切换类名就是一种很好的办法。
简介
svg
- 指可缩放矢量图形是基于可扩展标记语言(标准通用标记语言的子集),用于描述二维矢量图形的一种图形格式。
在 2003 年一月,SVG 1.1
被确立为 W3C 标准。
canvas
- 指在
HTML5
中新增的标签用于在网页实时生成图像,并且可以操作图像内容,基本上它是一个可以用JavaScript
操作的位图(bitmap)。
2014年10月29日,万维网联盟宣布,经过接近8年的艰苦努力,该标准规范终于制定完成。
能做什么?
svg 【查看demo】
SVG
文件可以直接插入网页,成为DOM
的一部分,然后用JavaScript
和CSS
进行操作。<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 - 矩形
- 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 bothanimation-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 CSSfrom&to&by
from
和to
分别定义发生变化的属性的初始值和终止值。from
可缺省,表示初始值即为<animate>
父元素相应的属性值。可用by
替换to
,表示变化偏移量。可以理解为to = from + by
。begin & dur & end
begin
定义动画开始时间;dur
定义动画所需时间;end
定义动画终止时间。时间单位h:小时;min:分钟;s:秒;ms:毫秒。默认时间单位为sfill
当fill="freeze"
时,动画终止时,发生变化的元素属性值停留在动画终止时的状态;当fill="remove"
时,动画终止时,发生变化的元素属性值回复到动画起始时的状态。
常见的曲线函数【查看demo】
通常而言,常见的图形绘制,或者运动轨迹之类,都是需要借助数学函数的。也就是要有一定的数学功力,无论是CSS3 transform
变幻还是我们平时所见的各种动画效果,其本质上都是数学函数运动和矩阵变换,因此,要想再图形可视化以及视觉动效领域有所建树,数学不能差。
了解下贝塞尔曲线cubic-bezier(<x1>, <y1>, <x2>, <y2>)
了解一下,如CSS3 animation
transition
的速度曲线函数。
应用
svg
- CSS3 clip-path + svg animate 实现图片切换动画【查看demo】
canvas
总结
考虑到兼容性的问题,在项目实践中,一般我们在桌面浏览器端任然推荐使用JavaScript
直接实现动画的方式或SVG
动画的实现方式,移动端则可以考虑使用CSS3
、canvas
或requestanimationFrame
。
感谢阅读 thx~
本文链接:https://627235655.github.io/2018/07/05/svg-and-canvas/