页面动画知识点整理

平时工作中会遇到需要实现一些存在动画的页面。这里对动画的实现知识做一个整理。
页面动画的实现可以分为两类:CSS动画、Canvas动画、JavaScript动画。JavaScript动画没啥好讲的,这里就不整理了。

CSS动画

CSS3中提供了一个属性transition,用来实现CSS样式的平滑变化。举个例子:

.box {
width: 100px;
height: 100px;
background: red;
transition: width 1s;
}
.box:hover {
width: 300px;
}
当鼠标hover到.box元素时,元素会在1s内逐渐的将宽度变化到300px。
具体效果可以去这里查看。

使用transition可以实现较为简单的动画。如果需要实现比较复杂的动画,可以使用amination来实现。举个例子:

@keyframes cssAmination {
0% {background: red; transform: skew(0deg);}
25% {background: yellow; transform: skew(-20deg);}
50% {background: blue; transform: skew(0deg);}
75% {background: green; transform: skew(20deg);}
100% {background: red; transform: skew(0deg);}
}
.amin {
animation: cssAmination 1s infinite ease;
}
在上的例子中,首先由keyframes定义一个动画叫做: cssAnimation。在cssAnimation中定义了动画过程中关键的5帧。每一帧都设置了当前帧的样式特征。然后在.amin节点上设置了动画属性animation,并将其设为前面定义的动画cssAnimation,每一次动画1秒,infinite表示无限循环,ease表示缓动方式,两个关键帧之间的变化是ease方式逐步变化的。
具体效果可以到这里查看

animation的缓动函数有很多类型的值,有一个值比较特别就是step[n[, start | end]]。step的效果是将keyframes中的每一个关键帧之间的切换并不是逐步变化的,而是到达某一关键帧后直接变化成新的关键帧样式,并保持不变,直到下一关键帧。所以使用step可以实现CSS3的帧动画。写法如下:

@keyframes cssFrameAmination {
0% {background-position: 0 0;}
25% {background-position: -100px 0;}
50% {background-position: -200px 0;}
75% {background-position: -300px 0;}
100% {background-position: -400px 0;}
}
.amin-frame {
background: url("./sprite.png") 0 0 no-repeat;
animation: cssFrameAmination 1s infinite step(5, start);
}
在上面的例子中,设置动画cssFrameAmination,其中每一关键帧都是精灵动画图片的一帧图片。然后在animation中设置animation-timing-function为step(5, start)表示动画分5帧。

有关CSS3动画相关的知识细节可以去这里了解。

Canvas

canvas是一个HTML标签,用于提供给脚本进行画图图形的绘制。canvas的绘制主要由CanvasRenderingContext2D的实例来进行绘制。CanvasRenderingContext2D 可以通过canvasDOM对象的getContext获得,代码如下:

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
getContext的参数是指在画布上绘制的类型,'2d'表示绘制二维图形。目前三维还没有实现,所以参数只支持'2d'。

绘制图形

canvas的上下文提供了众多的绘制方法。当你绘制一个图形时,基本思路是这样的:

  1. 调用save方法保存之前的样式状态

  2. 调用beginPath表示开始设置路径

  3. 调用fillStyle, strokeStyle等对接下来的路径进行样式设置

  4. 调用moveTo,lineTo, rect, arc等设置路径

  5. 调用closePath闭合路径

  6. 调用fill或者stroke对路径进行绘制

  7. 调用restore恢复之前保存的样式状态

上面过程中的save和restore的作用是将已经设置的样式进行保存和恢复。当存在多个图形时,前面的样式如果不恢复为默认样式,会影响到第二个图形的样式。使用save和restore可以保证每一个图形在绘制开始时,都是默认的样式。当然,你也可以不调用save和restore,而是通过将前面已经设置过的所有样式进行逐个的还原。
save可以保存的样式类型有:

  1. 当前应用的变形(即移动,旋转和缩放)

  2. strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation 的值

  3. 当前的裁切路径(clipping path)

步骤5closePath尽量不要忘记。原因和save,restore类似,如果忘记调用closePath就会导致前后图形间多绘制一根线。
我写了一个时钟的例子:github

下面对各类接口做了一个整理
样式设置

接口名
接口描述

颜色

fillStyle
图形填充颜色

strokeStyle
图形轮廓颜色

globalAlpha
图形全局透明度

阴影

shadowOffsetX, shadowOffsetY
阴影方向

shadowBlur
设定阴影的模糊程度

shadowColor
阴影的颜色值

线型

lineWidth
线条宽度(int)

lineCap
线条末端样式(butt: 平直; round: 添加半圆; square: 添加方形)

lineJoin
设置线条间的接合处(bevel: 斜角; round: 圆角; miter: 尖角)

miterLimit
两线相交时尖角最大长度(lineJoin:miter时生效,过长不显示)

getLineDash
返回当前虚线样式(数组)

setLineDash
设置虚线样式(数组)

lineDashOffset
设置虚线样式起始偏移量

渐变

createLinearGradient(x1, y1, x2, y2)
线性渐变

createRadialGradient(x1, y1, r1, x2, y2, r2)
圆渐变, 渐变反向是从圆心向外发散

gradient.addColorStop(position, color)
对生成的gradient对象添加结束颜色。position是中间过程,取值0~1

图案样式

createPattern(imageOrCanvas, type)
创建图片填充对象。image必须是已加载完毕的;type: repeat, repeat-x, repeat-y, no-repeat

路径

接口名
描述

moveTo(x, y)
移动路径绘制的起始点

beginPath()
新建一条路径

closePath()
闭合路径

lineTo(x, y)
从开始位置绘制路径到目标位置

rect(x, y, width, height)
绘制矩形路径

arc(x, y, radius, startAngle, endAngle, anticlockwise)
绘制圆弧:x,y为圆心;radius为半径;startAngle,endAngle为起止位置;anticlockwise为反向(顺时针,逆时针)

arcTo(x1, y1, x2, y2, radius)
绘制圆弧,并连接控制点

quadraticCurveTo(cp1x, cp1y, x, y)
x,y为结束点; cp1x,xp1y为控制点

bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
x,y为结束点;cp1x,cp1y为控制点1; cp2x,cp2y为控制点2

clip()
裁剪区域,区域外的不会发生绘制

绘制

接口名
描述

fillRect(x, y, width, height)
绘制填充矩形,等同于rect(); fill();

strokeRect(x, y, width, height)
绘制矩形边框。等同于rect(); stroke()

fill()
填充路径的内容区域

stroke()
通过路径线条绘制图形轮廓

清除

接口名
描述

clearRect(x, y, width, height)
清除指定矩形区域

文字

接口名
描述

font
设置文字样式,同css的font

textAlign
对其方式

textBaseLine
基线对其

direction
文本方向

fillText(text, x, y [, maxWidth])
绘制文字填充内容

strokeText(text, x, y [, maxWidth])
绘制文字边框内容

measureText(text)
返回文本的信息

样式保存

接口名
描述

save()
保存当前样式

restore()
恢复之前保存样式

绘制图片

canvas虽然可以绘制图形,但是最常用的应该是绘制图片。图片的绘制和图形的绘制类似。
canvas使用接口drawImage()进行接口绘制,接口定义如下:

drawImage(image, x, y, width, height, dx, dy, dWidth, dHeight);

其中的参数定义如下:

  1. image可以使HTMLImageElement, HTMLVideoElement(Video元素的某一帧), HTMLCanvasElement, ImageBitmap。

  2. x, y是指图片截取的起始位置。

  3. width, height是指图片截取的宽高。

  4. dx, dy是目标在Canvas中的起始坐标。

  5. dWidth, dHeight用于控制canvas绘制的图片的缩放大小。

图片变形

canvas还可以和CSS一样对图形进行变形转化。接口列表如下:

接口名字
描述

translate(x, y)
偏移。x,y是偏移量

rotate(angle)
旋转角度,顺时针

scale(x, y)
缩放。x, y分别是横轴,纵轴的缩放比例

transform(m11, m12, m21, m22, dx, dy)
变形矩阵转化

图形重叠处理

前面的例子中,当两个图形重叠后,都是由后面绘制的图形覆盖住前面绘制的图形。有时候需要改变这种情况。这种时候就可以使用globalCompositeOperation来进行设置(还可以用来遮盖,清除某些区域)。具体参数可以去这里查看

globalCompositeOperation: type

动画实现

使用上面的接口可以在canvas上绘制图片,但是都是固定的。当我们不断的对canvas进行重绘时,就可以达到动画的而效果。

动画的帧率达到60帧每秒时,也就是16ms没帧时,动画过程是流畅的。所以我们要对动画过程的绘制进行控制。有三个方法可以进行控制:

  1. setInterval。设置每16ms执行一次绘制过程。但是该方法存在一个问题,开始运行绘制函数的时间点可能处于某一帧的快结束时间点。这个时候绘制过程需要小于16ms才可以达到流畅。

  2. setTimeout。和setInterval类似。

  3. requestAnimationFrame。该方法会在浏览器每一次绘制结束后调用一次。使用该方法可以很好的避免setInterval和setTimeout出现的运行绘制函数时间不在每一帧开始的时间点。

Canvas性能

  1. 创建一个离屏canvas, 预先对复杂图形进行绘制。

  2. 避免浮点数的坐标点, 使用Math.floor()对坐标取整。

  3. 不要使用drawImage去缩放图片。

  4. 使用多canvas绘制复杂场景。

  5. 使用CSS设置大背景图。

Canvas调试

查了很多资料,发现Chrome 44版本之前是有Canvas调试功能的,但是Chrome 44之后,将Canvas调试功能去除了,并以扩展接口的方式提供功能。找了很久没有找到调试Canvas的扩展。另外,Firefox有提供专门的Canvas调试面板。试用了下,功能太少,对定位问题并没什么软用。
所以,关于调试的问题,只能试用传统的设断点,并逐步运行看效果进行调试。

关键字:css3动画, canvas, JavaScript

版权声明

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部