1、使用requestAnimationFrame
- 浏览器通过最优方式决定重绘时序。
1、早期定时动画
- 无法保证时间精度。
2、时间间隔问题
3、requestAnimationFrame
-
接收一个参数,是要在重绘屏幕前调用的函数。为了实现循环动画,可以多把个
requestAnimationFrame()串联起来。function updateProgress() { let div = document.getElementById('status') div.style.width = (parseInt(div.style.width, 10)+5)+ '%' if(div.style.left != '100%'){ requestAnimationFrame(updateProgress) } } requestAnimationFrame(updateProgress)- 只会调用一次所以需要循环调用,控制什么时候结束。
- 传入的函数可以接受一个参数,是DOMHighResTimeStamp实例
- 如
performance.now()的返回值。表示下次重绘的时间。
- 如
4、cancelAnimationFrame
- 返回一个请求ID,一用于通过另一个
cancelAnimationFrame()方法来取消重绘任务。
let requestID = window.requestAnimationFrame(()=>{
console.log('Repaint!')
})
window.cancelAnimationFrame(requestID)
5、通过requestAnimationFrame节流
-
递归地向队列中加入回调函数,可以保证每次重绘最多只调用一次回调函数
let enabled = true function expensiveOperation() { console.log("Invoked at", Date.now()) } window.addEventListener('scroll', ()=> { if(enabled) { enabled = false window.requestAnimationFrame(expensiveOperation) window.setTimeout(()=> enabled = true, 50) } })
2、基本画布功能
-
width、height属性,设置画布大小。 -
getContext():获取对绘图上下文的引用,平面图形传入"2d"参数。 -
toDataURL():导出<canvas>上的图像- 参数: MIME类型
let drawing = document.getElementById("drawing") if(drawing.getContext){ let imgURI = drawing.toDataURL("image/png") let image = document.createElement("img") img.src = imgURI document.body.appendChild(image) } -
如果画布中的图像是其他域绘制过来的,该方法会抛出错误。
3、2D绘图上下文
1、填充和描边
- 填充以指定样式(颜色、渐变或图像)自动填充形状,描边只为边界着色。
fillStyle:填充strokeStyle:描边- 属性可以是字符串、渐变对象或图案对象
- 默认"#000000"
- 字符串表示颜色可以是css任意格式
let drawing = document.getElementById("drawing")
if(drawing.getContext){
let context = drawing.getContext("2d")
context.strokeStyle = "red"
context.fillStyle = "#0000ff"
}
- 后面所有与描边和填充的相关操作都会用这两种样式,触发再次修改。
2、绘制矩形
-
fillRect():用来以指定颜色在画布上绘制并填充矩形 -
strokeRect():用来以指定颜色在画布上绘制矩形轮廓- 描边宽度:
lineWidth,整数 - 端点状态:
lineCap(butt平头、round出圆头、squre出方头) - 线条交点形状:
lineJoin(round圆转、bevel取平、miter出尖)
- 描边宽度:
-
clearRect():擦除画布中某个区域- 参数:矩形x坐标,矩形y坐标,矩形宽度,矩形高度
3、绘制路径
- 绘制路径要先调用
befinPath()表示要开始绘制路径 arc(x, y, radius, startAngle, endAngle, counterclockwise)- 以坐标(x, y) 为圆心,以radius为半径绘制一条弧线,起始角度startAngle,结束角度endAngle(弧度)。counterclockwise表示是否逆时针计算起始角度和结束角度(默认顺时针)
arcTo(x1, y1, x2, y2, radius)- 以给定半径radius,经由(x1, y1)绘制一条从上一点到(x2, y2)的弧线
bezierCurveTo(c1x, c1y, c2x, c2y, x, y)- 以(c1x, c1y),(c2x, c2y)为控制点绘制一条从上一点到(x,y)的弧线(三次贝塞尔曲线)
lineTo(x, y)- 绘制一条从上一点到(x, y)的直线
moveTo(x, y)- 不绘制线条,只把绘制光标移动到(x, y)
quadraticCurveTo(cx, cy, x, y)- 以(cx, cy) 为控制点,绘制一条从上一点到(x, y)的弧线(二次贝塞尔曲线)
rect(x, y, width, height)- 以给定的宽度和高度,在坐标点(x, y)绘制一个矩形。
- 与strokeRect和fillRect区别是创建的是一条路径而不是独立图形
- 创建路径后通过
closePath()方法绘制一条返回起点的线。如果路径已完成,可以- 指定
fillStyle属性并调用fill()方法来填充路径 - 指定
strokeStyle属性并调用stroke()方法来描画路径 - 调用
clip()方法基于已有路径创建一个新剪切区域
- 指定
isPointInPath(x, y)- (x, y)点是否在路径上
4、绘制文本
fillText()和strokeText()- 参数:要绘制的字符串、x坐标、y坐标、可选的最大像素宽度
- 基于属性
fontCSS语法指定的字体样式、大小、字体族等textAlign:指定文本对其方式- start、end、left、right、center
textBaseLine:文本的基线- top、hanging、middle、alphabetic、ideographic和bottom
measureText()用来辅助确定文本大小,接收一个参数,即要绘制的文本,返回一个TextMetrics对象,包含width属性。- 使用属性计算绘制指定文本后的大小
- 第四个参数:最大像素宽度如果超出最大宽度限制,字符会水平压缩。
5、变换
-
会以默认初始值变化矩阵。
-
rotate(angle):围绕原点把图像旋转angle角度 -
scale(scaleX, scaleY):通过在x轴乘以scaleX, 在y轴乘以scaleY来缩放图像,默认1.0 -
translate(x, y):把原点移到(x, y)。坐标(0, 0)会变成(x, y) -
transform(m1_1, m1_2, m2_1, m2_2, dx, dy):通过矩阵乘法修改矩阵m1_1 m1_2 dx m2_1 m2_2 dy 0 0 1 -
setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy):把矩阵重置为默认值,在以传入的参数调用transform -
所有的变换包括
fillStyle和strokeStyle属性,会一直保留在上下文直到再次修改。通过save()方法保存当前的状态,使用restore()方法回到之前保存的设置 -
只保存应用到绘图上下文的设置和变换,不保存绘图上下文的内容。
6、绘制图像
drawImage()- 三个参数:在画布上定位图像
- img,一个
<img>元素,或<canvas>元素 - x,表示绘制目标的x坐标
- y,表示绘制目标的y坐标
- img,一个
context.drawImage(img,x,y);
- 五个参数:在画布上定位图像,并规定图像的宽度和高度
- img,一个
<img>元素,或<canvas>元素 - x,表示绘制目标的x坐标
- y,表示绘制目标的y坐标
- width,目标宽度
- height,目标高度
- img,一个
context.drawImage(img,x,y,width,height);
- 九个参数:剪切图像,并在画布上定位被剪切的部分
- img,一个
<img>元素,或<canvas>元素 - sx,源图像x坐标
- sy,源图像y坐标
- swidth,源图像宽度
- sheight,源图像高度
- x,表示绘制目标的x坐标
- y,表示绘制目标的y坐标
- width,目标宽度
- height,目标高度
- img,一个
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
7、阴影
- 属性设置
shadowColor:要绘制的阴影颜色,默认黑色shadowOffsetX:阴影相对于形状或路径的x坐标的偏移量,默认0shadowOffsetY:阴影相对于形状或路径的y坐标的偏移量,默认0shadowBlur:像素,表示阴影的模糊量,默认0
8、渐变
createLineGradient()创建线性渐变- 参数:起点x坐标、起点y坐标、终点x坐标、终点y坐标
- 返回
gradient实例- 实例使用
addColorStop()为渐变指定色标- 参数:色标位置(0 ~ 1),CSS字符串
- 设置完毕后把该实例赋给fillStyle或strokeStyle来绘制图形。
- 实例使用
createRadialGradient()创建径向渐变- 参数:起点圆形中心x,y和半径,终点x,y和半径
- 返回
gradient实例- 实例使用
addColorStop()为渐变指定色标- 参数:色标位置(0 ~ 1),CSS字符串
- 设置完毕后把该实例赋给fillStyle或strokeStyle来绘制图形。
- 实例使用
9、图案
- 图案用于填充和描画图形的重复图像
createPattern()传入两个参数<img>元素(或<video>、<canvas>)- 如何重复图像:repeat、repeat-x、repeat-y、no-repeat
- 图案的起点是画布原点(0, 0)
10、图像数据
getImageData()获取原始图像数据- 四个参数:
- 要取得图像数据中第一个像素的左上角坐标
- 要取得的像素宽度及高度
- 返回ImageData的实例,包含width、height、data三个属性
- data是包含图像的元素像素信息的数组,由红、绿、蓝和透明度表示(第一个像素占据0 - 3 四个值)
- 四个参数:
11、合成
-
globalAlpha- 范围 0 - 1 指定所有绘制内容的透明度,默认0
-
globalCompositionOperation,表示新绘制的形状如何与上下文中已有的形状融合-
source-over:默认值,新图形绘制在原有图形上面。 -
source-in:新图形只绘制出与原有图形重叠的部分,画布上其余部分全部透明。 -
source-out:新图形只绘制出不与原有图形重叠的部分,画布上其余部分全部透明。 -
source-atop:新图形只绘制出与原有图形重叠的部分,原有图形不受影响。 -
destination-over:新图形绘制在原有图形下面,重叠部分只有原图形透明像素下的部分可见。 -
destination-in:新图形绘制在原有图形下面,画布上只剩下二者重叠的部分,其余部分完全透明。 -
destination-out:新图形与原有图形重叠的部分完全透明,原图形其余部分不受影响。 -
destination-atop:新图形绘制在原有图形下面,原有图形与新图形不重叠的部分完全透明。 -
lighter:新图形与原有图形重叠部分的像素值相加,使该部分变亮。 -
copy:新图形将擦除并完全取代原有图形。 -
xor:新图形与原有图形重叠部分的像素执行“异或”计算
-
4、WebGL
1、WebGL上下文
let drawing = document.getElementById("drawing")
if(drawing.getContext) {
let gl = drawing.getContext("webgl")
if(gl) {
...
}
}