目录
(1)线性渐变 createLinearGradient();
(2)径向渐变 createRadialGradient(x, y, r, x1, y1, r1);
22、图像的合成样式 globalCompositeOperation
考虑浏览器的支持(基本上都支持了):
支持 <canvas> 的浏览器会只渲染 <canvas> 标签,而忽略其中的替代内容。不支持 <canvas> 的浏览器则 会直接渲染替代内容。
用文本替换:
<canvas> 你的浏览器不支持 canvas,请升级你的浏览器。 </canvas>
用 <img> 替换:
<canvas> <img decoding="async" src="./temp.jpg"> </canvas>
基本格式:
<canvas id="c1" width="1000" height="500"></canvas>
// 拿到画布
let c1 = document.getElementById('c1');
if(c1.getContext){
// 拿到画笔 有画布和画笔就可以画图了
let brush = c1.getContext('2d');
}
1、绘制矩形
canvast 提供了三种方法绘制矩形:
- 1、fillRect(x, y, width, height):绘制一个填充的矩形。
- 2、strokeRect(x, y, width, height):绘制一个矩形的边框。
- 3、clearRect(x, y, widh, height):清除指定的矩形区域,然后这块区域会变的完全透明。
说明:这 3 个方法具有相同的参数。
- x, y:指的是矩形的左上角的坐标。(相对于canvas的坐标原点)
- width, height:指的是绘制的矩形的宽和高
2、路径
使用路径绘制图形需要一些额外的步骤:
- 创建路径起始点
- 调用绘制方法去绘制出路径
- 把路径封闭
- 一旦路径生成,可以通过描边或填充路径区域来渲染图形。
下面是需要用到的方法:
- beginPath() 新建一条路径,路径一旦创建成功,图形绘制命令被指向到路径上生成路径
- moveTo(x, y) 把画笔移动到指定的坐标(x, y)。相当于设置路径的起始点坐标。
- closePath() 闭合路径之后,图形绘制命令又重新指向到上下文中
- stroke() 通过线条来绘制图形轮廓
- fill() 通过填充路径的内容区域生成实心的图形
- lineTo(x, y) 绘制从当前位置到指定坐标x,y的一条直线
3、三个方法绘制圆弧:
1、arc(x, y, r, startAngle, endAngle, anticlockwise):
以(x, y) 为圆心,以r 为半径,从 startAngle 弧度开始到endAngle弧度结束。anticlosewise 是布尔值,true 表示逆时针,false 表示顺时针(默认是顺时针)。
2、arcTo(x1, y1, x2, y2, radius):
根据给定的控制点和半径画一段圆弧,最后再以直线连接两个控制点 ;控制点x1,y1,终点x2,y2,起点到终点的角度。
3、
ctx.beginPath();
// 起始点 50 50
ctx.moveTo(50, 50);
//参数1、2:控制点1坐标 ,参数3、4:控制点2坐标,参数5:圆弧半径
ctx.arcTo(200, 50, 200, 200, 100);
ctx.lineTo(200, 200);
ctx.stroke();
arcTo 方法的说明:
这个方法可以这样理解:绘制的弧形是由两条切线所决定。
第 1 条切线:起始点 和 控制点1决定的直线。
第 2 条切线:控制点1 和 控制点2决定的直线。
4、绘制二次、三次贝塞尔曲线
quadraticCurveTo(cp1x, cp1y, x, y)
需要一个起始点
参数1、2:控制点坐标,
参数3、4:结束点坐标。
5、绘制三次贝塞尔曲线:
同样需要一个起始点,
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
- 参数 1 和 2:控制点 1 的坐标
- 参数 3 和 4:控制点 2 的坐标
- 参数 5 和 6:结束点的坐标
6、线条的颜色
两个属性
fillStyle = color 设置填充颜色 strokeStyle = color 设置图形轮廓的颜色
备注:
1. color 可以是表示 css 颜色值的字符串、渐变对象或者图案对象。
2. 默认情况下,线条和填充颜色都是黑色。
3. 一旦设置了 strokeStyle 或者 fillStyle 的值,那么这个新值就会成为新绘制的图形的默认值。如果要给每个图形上不同的颜色,需要重新设置 fillStyle 或 strokeStyle 的值。
设置图案样式:
// 图案样式
let img = new Image();
img.src = 'https://xxxxxxx.xxx.xx.cn';
img.onload = function (){ // 等图片加载好了再开始画
// 设置图案 第一个参数是 图片对象,第二个参数是 决定图案是否重复
let pattern = pencil.createPattern(img, 'no-repeat');
pencil.fillStyle = pattern;
pencil.fillRect(0, 0, 600, 600);
}
7、线宽
属性:lineWidth
ctx.lineWidth = 20;
8、线条末端样式
属性:lineCap
共有三个值:
1、butt:线条末端以方形结束
2、round:线条末端以圆形结束
3、square: 线段末端以方形结束,但是增加了一个宽度和线段相同,高度是线段厚度一半的矩形区域
9、同一个 path 内,设定线条与线条间接合处的样式
属性:lineJoin
取值:
1、round :通过填充一个额外的,圆心在相连部分末端的扇形,绘制拐角的形状。 圆角的半径是线段的宽度。
2、bevel :在相连部分的末端填充一个额外的以三角形为底的区域, 每个部分都有各自独立的矩形拐角。
3、miter:(默认) 通过延伸相连部分的外边缘,使其相交于一点,形成一个额外的菱形区域。
10、绘制虚线
用 setLineDash 方法和 lineDashOffset 属性来制定虚线样式。
setLineDash 方法接受一个数组,来指定线段与间隙的交替;
lineDashOffset 属性设置起始偏移量。
ctx.setLineDash([20, 5]); // [实线长度, 间隙长度]
ctx.lineDashOffset = -0;
tx.strokeRect(50, 50, 210, 210);
11、绘制文本的两种方法
- fillText(text, x, y [, maxWidth]) 在指定的 (x,y) 位置填充指定的文本,绘制的最大宽度是可选的。
- strokeText(text, x, y [, maxWidth]) 在指定的 (x,y) 位置绘制文本边框,绘制的最大宽度是可选的。
ctx.font = "100px sans-serif";
ctx.fillText("难得逍遥", 10, 100);
ctx.strokeText("天若有情", 10, 200);
12、获取文本的宽度
cxt.measureText(text).width 得到文本的宽度
13、设置文本对齐方式
使用 textAlign (需要在设置字体大小和类型之后)
brush.font = '30 楷书';
crush.textAlign = 'center';
crush.strokeText('江南好,风景旧曾谙', 375, 250);
14、给文本添加样式
- font = value 当前我们用来绘制文本的样式。这个字符串使用和 CSS font 属性相同的语法。 默认的字体是 10px sans-serif。
- textAlign = value 文本对齐选项。 可选的值包括:start, end, left, right, center。 默认值是 start。
- textBaseline = value 基线对齐选项,可选的值包括:top, hanging, middle, alphabetic, ideographic, bottom。默认值是 alphabetic。。
- direction = value 文本方向。可能的值包括:ltr, rtl, inherit。默认值是 inherit。
15、使用 Path2D 封装路径
// 使用 Path2D 封装路径
let arcPath = new Path2D(); // 创建Path2D对象
arcPath.arc(100, 100, 90, 0, Math.PI * 1.4); // 该对象是专门画一个圆的
pencil.stroke(arcPath); // 利用画笔将这个对象要画的图形轮廓画出来
pencil.fill(arcPath); // 填充
16、设置全局透明度
属性:globalAlpha
ctx.globalAlpha = 0.4;
17、渐变
(1)线性渐变 createLinearGradient();
// canvas 设置线性渐变
let clg = pencil.createLinearGradient(100, 100, 300, 300); // 对角线渐变 渐变起始点坐标 左上至右下
clg.addColorStop(0, '#fff');
clg.addColorStop(1, 'blue');
pencil.fillStyle = clg; // 按规定的渐变色进行填充
pencil.fillRect(100, 100, 300, 300); // 绘制矩形,矩形的范围刚好是渐变的范围
(2)径向渐变 createRadialGradient(x, y, r, x1, y1, r1);
// 设置径向渐变
// 径向渐变 内圆圆心的坐标+半径 外圆圆心的坐标+半径
let crl = pencil.createRadialGradient(300, 300, 1, 300, 300, 200);
crl.addColorStop(0, 'yellow');
crl.addColorStop(1, 'green');
pencil.fillStyle = crl; // 规定在指定的范围内进行填充
pencil.fillRect(100, 100, 500, 500);
(3)圆锥渐变
// 圆锥渐变
pencil.beginPath();
// 起始的角度,圆心位置 范围是整个画布
let ccg = pencil.createConicGradient(0, 300, 300);
ccg.addColorStop(0, '#fff');
ccg.addColorStop(1, '#888');
pencil.fillStyle = ccg;
pencil.arc(300, 300, 600, 0, Math.PI * 2);
pencil.fill();
pencil.closePath();
pencil.beginPath();
pencil.arc(300, 300, 80, 0, Math.PI * 2);
pencil.fillStyle = '#fff';
pencil.fill();
pencil.closePath();
18、阴影颜色
// 设置阴影
pencil.shadowOffsetX = 10; // 水平的偏移量
pencil.shadowOffsetY = 10; // 垂直的偏移量
pencil.shadowBlur = 5; // 模糊度
pencil.shadowColor = 'pink'; // 阴影颜色
pencil.arc(300, 300, 100, 0, Math.PI *2);
pencil.stroke();
19、绘制图片的三种方式
// 绘制图片的三种方式
let img = new Image();
img.src = './picture.webp';
// 等图片加载好了就开始绘制
img.onload = function (){
// 第一种方式,没有任何缩放, 第一个参数是图片的对象,后两个参数为图片放置的位置
// pencil.drawImage(img, 0, 0);
// 第二种方式 第一个参数为图片对象,第二三个参数为图片放置的位置(最左上角的坐标),后两个参数为原图片宽和高分别缩放到多少
// pencil.drawImage(img, 0, 0, 600, 600);
// 第三种方式 第一个参数为图片对象,第二三个参数为对原图片矩形裁剪的起始坐标,第四五个参数为裁剪的矩形的大小,第六七个参数
// 为将图片放到画布上的起始点,第八九个参数为缩放的比例,这里裁剪的结果和画布的大小一致,则不用缩放
pencil.drawImage(img, 50, 50, 600, 600, 0, 0, 600, 600);
}
canvas 的图片右键点击可以下载,但下载下来的是经过canvas处理的图片,而不是原来的图片
20、canvas 处理视频
<canvas id="canvas1" width="600" height="600"></canvas>
<button class="btn">start video OR puase video</button>
<video
src="./391092495_401692.MP4"
width="300"
height="300"
controls
hidden
></video>
// canvas 重绘视频
let video = document.getElementsByTagName('video')[0]; // 获取原有的视频对象
let img = new Image(); // 构造水印图片
img.src = 'https://img2.baidu.com/it/u=2425133085,3559224002&fm=253&fmt=auto&app=138&f=JPEG?w=450&h=450';
let btn = document.getElementsByClassName('btn')[0];
btn.onclick = function(){ // 用户触发点击事件时 播放视频,并实时将画面绘制到canvas画布上
if(video.paused){ // 做出判断,当前播放则暂停,当前暂停则继续播放
video.play();
render();
}else{
video.pause();
}
}
function render(){
pencil.drawImage(video, 0, 0, 600, 600); // 注意顺序,先视频,再水印
pencil.drawImage(img, 0, 0, 100, 100);
requestAnimationFrame(render); // 重复绘制的动画
}
html 中对 video 设置属性 hidden 将原视频隐藏,则用户只能看见的是 canvas 中的内容。
而 video 也可以在 js 中自行构造
21、变换
注意 :
位移、缩放、旋转 变化的都是整个坐标系,所以要先进行坐标轴变换,再绘制图形。
(1)位移
// 位移 translate 注意 位移的是坐标系
pencil.fillRect(0,0,50,50); // 在原坐标系下作矩形
pencil.translate(50,50); // 坐标系整体向下和向右各位移50 原来的图形不受影响
pencil.fillRect(0,0,50,50); // 在新的坐标系下作图
需要注意的是,translate 位移 是对坐标轴的位移,原来绘制好的图形不会再受影响
(2)缩放
// 缩放 scale 仍然是对坐标系的缩放
pencil.strokeRect(0, 0, 50, 50); // 原来的图形
pencil.scale(3, 2); // 水平 放大到原来的三倍,竖直放大到原来的两倍
pencil.strokeRect(0, 0, 50, 50);
(3)旋转
// 旋转 rotate
pencil.rotate(Math.PI / 4); // 将画布整体旋转 45度
pencil.strokeRect(100, 100, 50, 50);
(4)使用变换矩阵 transform
22、图像的合成样式 globalCompositeOperation
共有26中属性值
Canvas学习:globalCompositeOperation详解
使用 destination-out 实现一个刮刮卡
<body>
<div class="text">特等奖!!!</div>
<canvas id="c1" width="600" height="600">你的浏览器不支持canvas</canvas>
</body>
<style>
html,body{
position: relative;
}
.text {
width: 600px;
height: 600px;
text-align: center;
line-height: 600px;
font-size: 2rem;
position: absolute;
z-index: 0;
}
#c1 {
position: absolute;
top: 0;
left: 0;
z-index: 10;
}
</style>
<script>
let canvas = document.getElementById('c1');
if (canvas.getContext) { // 判断是否可用 canvas
let pencil = canvas.getContext('2d'); // 获取上下文对象,创建画笔
pencil.fillStyle = 'rgba(245,0,0,1)'; // 先填充好内容 覆盖
pencil.fillRect(0, 0, 600, 600);
var isClear = false; // 是否可刮
// 注意 监听的是 canvas元素 即画布,不是画笔
canvas.onmousedown = function () { // 监听鼠标点击事件
isClear = true; // 鼠标按下则可刮
}
canvas.onmouseup = function () { // 抬起鼠标键 不可刮
isClear = false;
}
canvas.onmousemove = function (e) {
if (isClear) {
pencil.globalCompositeOperation = 'destination-out'; // 设置图形重叠的方式
pencil.arc(e.pageX, e.pageY, 10, 0, Math.PI * 2); // 在鼠标周围刮一个圆
pencil.fill(); // 填充
}
}
}
</script>
23、根据路径进行裁剪
裁剪后,除参照对象以外,其他区域都变成透明
pencil.clip() // 默认按照前面的图形进行裁剪
pencil.clip(obj of Path2D) // 传入一个 Path2D 的对象,则画布按照该对象的范围进行裁剪
24、状态保存与恢复
储存在栈中,将上一次的样式推到栈顶,恢复时,从栈顶取出上一次使用过的样式。
pencil.save();
pencil.restore();
25、判断一个点是否在路径范围之内
pencil.isPointInPath(路径对象,x,y) ,返回boolean值
26、清空画布的三种方法
1、使用一个背景色填充画布:
brush.fillStyle = '#ffffff';
brush.fill(0, 0, canvas.width, canvas.height);
2、清空区域的方法 clearReat()
brush.clearRect(0, 0, canvas.width, canvas.height);
3、重设 canvas 的宽高
let width = canvas.width;
let height = canvas.height;
canvas.width = width;
canvas.height = height;