《JavaScript高级程序设计》读书笔记
requestAnimationFrame
告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。
cancelAnimationFrame 取消重绘任务
let requestID = window.requestAnimationFrame(() => {
console.log('Repaint!');
});
window.cancelAnimationFrame(requestID);
节流
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);
}
});
画布功能
坐标原点在左上角
- getContext() 方法获取对绘图上下文的引用
- toDataURL() 导出<canvas> 元素上的图像,接受一个参数:要生成图像的MIME类型
- fillStyle:填充
- strokeStyle:描边
1. 绘制矩形
这3个方法都接收 4 个参数:矩形 x 坐标、矩形 y 坐标、矩形宽度和矩形高度。单位:像素。
- fillRect() 方法用于以指定颜色在画布上绘制并填充矩形。填充的颜色使用 fillStyle 属性指定
- strokeRect() 方法使用通过 strokeStyle 属性指定的颜色绘制矩形轮廓
- clearRect() 方法擦除画布中某个区域
let drawing = document.getElementById("drawing");
if(drawing.getContext){
let context = drawing.getContext("2d");
context.fillStyle = '#0000ff';
context.fillRect(10, 10, 50, 50);
context.fillStyle = 'rgba(0,0,255,0.5)';
context.fillRect(80, 10, 10, 50);
context.strokeStyle = "red";
context.strokeRect(10, 10, 50, 50);
context.clearRect(40, 40, 10, 10);
let imgUrl = drawing.toDataURL("image/png");
let image = document.createElement("img");
image.src = imgUrl;
document.body.appendChild(image);
}
2. 绘制路径
首先调用 beginPath()方法表示要开始绘制新路径。然后调用下列方法绘制路径:
- 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) 方法用于确定指定的点是否在路径上,可以在关闭路径前随时调用
let drawing = document.getElementById("drawing");
if(drawing.getContext){
let context = drawing.getContext("2d");
context.beginPath();
context.arc(100, 100, 99, 0, 2 * Math.PI, false);
context.moveTo(194, 100);
context.arc(100, 100, 94, 0, 2 * Math.PI, false);
context.moveTo(100, 100);
context.lineTo(100, 15);
context.moveTo(100, 100);
context.lineTo(35, 100);
context.stroke();
}
3. 绘制文本
接收 4 个参数:要绘制的字符串、 x 坐标、 y 坐标和可选的最大像素宽度
- fillText()
- strokeText()
这两个方法最终绘制的结果都取决于以下 3 个属性:
- font:以 CSS 语法指定的字体样式、大小、字体族等,比如"10px Arial"。
- textAlign:指定文本的对齐方式,包括"start"、 "end"、 "left"、 "right"和"center"。推荐使用"start"和"end"。
- textBaseLine:指定文本的基线,包括"top"、"hanging"、"middle"、"alphabetic"、"ideographic"和"bottom"。
measureText(str):检查字体宽度
let drawing = document.getElementById("drawing");
if(drawing.getContext){
let context = drawing.getContext("2d");
context.font = "bold 14px Arial";
context.textAlign = "center";
context.fillStyle = "red";
context.fillText("Hello", 100, 20);
console.log(context.measureText("Hello"))
}
4. 变换
- rotate(angle):围绕原点把图像旋转 angle 弧度。
- scale(scaleX, scaleY):通过在 x 轴乘以 scaleX、在 y 轴乘以 scaleY 来缩放图像。 scaleX和 scaleY 的默认值都是 1.0。
- translate(x, y):把原点移动到(x, y)。执行这个操作后,坐标(0, 0)就会变成(x, y)。
- transform(m1_1, m1_2, m2_1, m2_2, dx, dy): 替换绘图的当前转换矩阵。
- setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy):将当前转换重置为单位矩阵。然后运行 transform()。
5. 绘制图像
drawImage() 提供 9 个参数:要绘制的图像、源图像 x 坐标、源图像 y 坐标、源图像宽度、源图像高度、目标区域 x 坐标、目标区域 y 坐标、目标区域宽度和目标区域高度。
context.drawImage(image, 50, 10, 20, 30);
6. 阴影
- shadowColor: CSS 颜色值,表示要绘制的阴影颜色,默认为黑色。
- shadowOffsetX:阴影相对于形状或路径的 x 坐标的偏移量,默认为 0。
- shadowOffsetY:阴影相对于形状或路径的 y 坐标的偏移量,默认为 0。
- shadowBlur:像素,表示阴影的模糊量。默认值为 0,表示不模糊。
7. 渐变
- createLinearGradient()方法:创建线性渐变,接收 4 个参数:起点 x 坐标、起点 y 坐标、终点 x 坐标和终点 y 坐标。创建一个新的 CanvasGradient对象并返回实例
- createRadialGradient()方法:径向渐变(或放射性渐变),接收 6 个参数:渐变的开始圆的 x 坐标、渐变的开始圆的 y 坐标、开始圆的半径、渐变的结束圆的 x 坐标、渐变的结束圆的 y 坐标、结束圆的半径
- addColorStop()方法:渐变指定色标,接收两个参数:色标位置和 CSS 颜色字符串
let gradient = context.createLinearGradient(30, 30, 70, 70);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "black");
8. 图案
- createPattern()方法并传入两个参数:一个 HTML <img>元素和一个表示该如何重复图像的字符串("repeat"、 "repeat-x"、 "repeat-y"和"no-repeat")。
let image = document.images[0],
pattern = context.createPattern(image, "repeat");
9. 图像数据
- getImageData()方法获取原始图像数据。这个方法接收 4 个参数:开始复制的左上角位置的x 坐标和y 坐标,要取得区域的宽度和高度。返回的对象是一个 ImageData 的实例,包含 3 个属性: width、 height 和 data(图像的原始像素信息的数组)。
- putImageData()方法:把图像数据再绘制到画布上
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle="red";
ctx.fillRect(10,10,50,50);
function copy(){
var imgData=ctx.getImageData(10,10,50,50);
ctx.putImageData(imgData,10,70);
}
10. 合成
- globalAlpha:设置或返回绘图的当前 alpha 或透明值。context.globalAlpha = 0.5
- globalCompositeOperation:设置或返回新图像如何绘制到已有的图像上。context.globalCompositeOperation="destination-over";
- source-over:默认值,新图形绘制在原有图形上面。
- source-in:新图形只绘制出与原有图形重叠的部分,画布上其余部分全部透明。
- source-out:新图形只绘制出不与原有图形重叠的部分,画布上其余部分全部透明。
- source-atop:新图形只绘制出与原有图形重叠的部分,原有图形不受影响。
- destination-over: 新图形绘制在原有图形下面,重叠部分只有原图形透明像素下的部分可见。
- destination-in:新图形绘制在原有图形下面,画布上只剩下二者重叠的部分,其余部分完全透明。
- destination-out:新图形与原有图形重叠的部分完全透明,原图形其余部分不受影响。
- destination-atop:新图形绘制在原有图形下面,原有图形与新图形不重叠的部分完全透明。
- lighter:新图形与原有图形重叠部分的像素值相加,使该部分变亮。
- copy:新图形将擦除并完全取代原有图形。
- xor:新图形与原有图形重叠部分的像素执行“异或”计算