目录
Canvas 是 HTML5 新增的元素,它就像一块幕布,可通过JavaScript脚本在 Web 页面上绘制图形、动画和其他可视化内容
设置 Canvas
一种是在 HTML 中直接通过 width 和 height 属性来设置,不能通过 style 设置
- 如果只通过 CSS 来设置的尺寸,会导致图形变形,因为 CSS 改变的是画布的显示大小,而不是实际的绘图区域大小
<canvas id="myCanvas" width="400" height="300"></canvas>
另一种是在 JavaScript 中通过设置 canvas 对象的 width 和 height 属性来实现
var canvas = document.getElementById('myCanvas');
canvas.width = 400;
canvas.height = 300;
绘图上下文系统
const ctx = canvas.getContext('2d'); // 获取 2D 渲染上下文
const webgl = canvas.getContext('webgl'); // 3D 上下文(需支持 WebGL)
渲染模式对比
模式 | 特性 | 适用场景 |
---|---|---|
2D | 基于矢量图形,支持路径、渐变、阴影等传统绘图 | UI 元素、数据可视化 |
WebGL | 基于 OpenGL ES 的硬件加速 3D 渲染,支持着色器编程 | 复杂 3D 动画、游戏 |
<!--1.创建画布-->
<canvas id="myCanvas"></canvas> // 如果没有设置宽高,那么会自动创建一个 300 * 150 的画布(单位默认为 px)
// 2.获取绘图上下文
const canvas = document.getElementById('myCanvas') // 获取画布节点
const ctx = canvas.getContext('2d') // 代表一个二维渲染上下文
// 3.设置绘制属性
canvas.width = 500 // 设置画布宽度
canvas.height = 500 // 设置画布高度
ctx.fillText('我是文本', 30, 20) // 绘制文本内容和坐标
ctx.fillStyle = 'red' // 设置填充颜色
ctx.font = '18px Arial' // 设置文本大小和字体
ctx.textAlign = 'center' // 设置水平对齐方式
ctx.textBaseline = "middle" // 设置垂直对齐方式
ctx.setLineDash([5, 5]) // 设置虚线
ctx.lineWidth = 2 // 设置线条宽度为2像素
// 4.绘制矩形
ctx.fillRect(10, 10, 10, 10) // 绘制填充矩形
ctx.strokeRect(70, 10, 50, 50) // 绘制描边矩形
// 5.绘制路径
ctx.beginPath() // 开始新路径
ctx.moveTo(100, 100) // 移动到起始点
ctx.lineTo(150, 150) // 创建直线路径
ctx.lineTo(200, 100) // 创建直线路径
ctx.closePath() // 关闭路径
ctx.stroke() // 描边路径
ctx.fill() // 填充路径
// 6.清除画布内容
ctx.clearRect(0, 0, canvas.width, canvas.height)
核心绘图功能
文字
可以使用 fillText() 方法在 Canvas 上绘制填充的文字,使用 strokeText() 方法绘制文字的轮廓
- 设置字体:使用 font 属性来设置文字的字体、大小和样式。例如:ctx.font = ‘20px Arial’ 设置字体为 20 像素大小的 Arial 字体。
- 设置颜色:使用 fillStyle 属性设置填充文字的颜色,使用 strokeStyle 属性设置文字轮廓的颜色。例如:ctx.fillStyle = ‘blue’ 设置填充文字为蓝色。
- 设置对齐方式:
-
使用 textAlign 属性设置文字的水平对齐方式,,它定义了文字相对于指定 x 坐标的对齐方式。可以是 start、end、left、center、right。
-
使用 textBaseline 属性设置文字的垂直对齐方式,它定义了文字相对于指定 y 坐标的对齐方式。可以是 top、hanging、middle、alphabetic、ideographic、bottom。
-
textAlign值 | 描述 |
---|---|
left | 文字的左边缘与指定的 x 坐标对齐。 |
right | 文字的右边缘与指定的 x 坐标对齐。 |
center | 文字的水平中心点与指定的 x 坐标对齐。 |
start | 默认值,文字从指定的 x 坐标开始绘制。对于从左到右的语言(如英语、中文),等同于 “right”;对于从右到左的语言(如阿拉伯语),等同于 “left”。 |
end | 文字在指定的 x 坐标结束绘制。对于从左到右的语言,等同于 “right”;对于从右到左的语言,等同于 “left”。 |
textBaseline值 | 描述 |
---|---|
top | 文字的顶部与指定的 y 坐标对齐。 |
hanging | 文字的悬挂基线(靠近顶部)与指定的 y 坐标对齐(主要用于某些语言的手写体或特定字体)。 |
middle | 文字的垂直中心点与指定的 y 坐标对齐。 |
alphabetic | 默认值,文字的字母基线(默认值)与指定的 y 坐标对齐(适用于大多数拉丁字母和中文)。 |
ideographic | 文字的表意基线(靠近底部)与指定的 y 坐标对齐(主要用于中文、日文等表意文字)。 |
bottom | 文字的底部与指定的 y 坐标对齐。 |
- 阴影效果:使用 shadowColor 属性设置阴影的颜色,shadowOffsetX 和 shadowOffsetY 属性设置阴影的偏移量,shadowBlur 属性设置阴影的模糊程度。
- 轮廓效果:可以先使用 strokeStyle 设置轮廓颜色,然后使用 strokeText() 方法绘制文字轮廓。
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.fillText('Hello, World!', 50, 50);
ctx.strokeText('Hello, World!', 100, 100);
ctx.font = '30px Arial';
ctx.fillStyle = 'red';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('Hello, World!', canvas.width / 2, canvas.height / 2);
ctx.shadowColor = 'gray';
ctx.shadowOffsetX = 5;
ctx.shadowOffsetY = 5;
ctx.shadowBlur = 3;
ctx.fillText('Hello, World!', 50, 50);
ctx.strokeStyle = 'blue';
ctx.lineWidth = 2;
ctx.strokeText('Hello, World!', 100, 100);
实现文本居中
ctx!.textAlign = "center"
ctx!.textBaseline = "middle"
ctx!.fillText("啥",canvasRef.width / 2,canvasRef.height / 2)
直线
使用 moveTo(x1,y1) 和 lineTo(x2,y2) 方法来绘制直线。moveTo 方法用于设置线条的起始点,lineTo 方法用于设置线条的结束点。然后可以使用 stroke() 方法来绘制线条。
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(0, 5);
ctx.lineTo(80, 100);
ctx.stroke();
矩形
- 使用 fillRect(x,y,width,height) 方法来绘制填充的矩形,
- 使用 strokeRect(x,y,width,height) 方法来绘制矩形边框
- ctx.rect(x,y,width,height),绘制为填充、未描边的矩形,需要手动填充或描边
// fillRect绘制填充矩形,默认填充颜色为黑色,且自动填充
ctx.fillRect(0,0,100,100);
// 或者通过rect绘制矩形,但是需要显性设置fillStyle,并手动执行fill填充
ctx.fillStyle = 'red';
ctx.rect(0,0,100,100)
ctx.fill();
圆形
通过使用 arc(x,y,radius,startAngle,endAngle,anticlockwise) 方法来绘制圆形。
- 其中 x 和 y 是圆心的坐标,radius 是半径,
- startAngle 和 endAngle 是起始角度和结束角度(以弧度为单位),
- anticlockwise 是一个布尔值,表示是否逆时针绘制,
ctx.beginPath();
ctx.arc(200, 200, 50, 0, 2 * Math.PI);
ctx.stroke();
路径
- beginPath():开始一个新的路径。每次在绘制新的图形之前,最好先调用这个方法,以确保不会影响到之前的路径。
- moveTo(x, y):将绘图光标移动到指定的坐标点,这个点将成为后续线条的起始点。
- lineTo(x, y):从当前位置绘制一条直线到指定的坐标点。
- closePath():如果路径是开放的,这个方法会将路径的最后一点与起始点连接起来,形成一个封闭的形状。
// 绘制弧形
ctx.beginPath(); // 重置路径[
ctx.moveTo(100, 100); // 起点
ctx.arc(150, 150, 50, 0, Math.PI*2);
ctx.lineTo(150, 150)
ctx.closePath(); // 闭合路径
ctx.stroke(); // 描边
图像
使用 drawImage() 方法在 Canvas 上绘制图像。这个方法有三种不同的参数形式:
drawImage(image, x, y):在指定位置(x,y)绘制图像。这里的 image 可以是一个 元素、一个 Canvas 对象或者一个 Video 对象。
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = 'your-image.jpg';
img.onload = function() {
ctx.drawImage(img, 0, 0);
};
图形的填充和描边
- 填充:使用 fill() 方法对封闭的路径进行填充。可以通过设置 fillStyle 属性来指定填充的颜色。
- 描边:使用 stroke() 方法对路径进行描边。可以通过设置 strokeStyle 属性来指定线条的颜色,设置 lineWidth 属性来指定线条的宽度。
ctx.fillStyle = 'blue';
ctx.fill(); // 填充路径
ctx.strokeStyle = 'red';
ctx.lineWidth = 3;
ctx.stroke(); // 描边路径
图形变换
平移
使用 translate(x, y) 方法可以将坐标原点移动到指定的位置,从而实现图形的平移。x 和 y 分别表示在 x 轴和 y 轴上的位移量。
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.fillRect(10, 10, 50, 50);
ctx.translate(50, 50);
ctx.fillRect(10, 10, 50, 50);
旋转
- 使用 rotate(angle) 方法可以将图形围绕坐标原点旋转指定的角度。角度以弧度为单位。
ctx.fillRect(10, 10, 50, 50);
ctx.rotate(Math.PI / 4); // 旋转 45 度
ctx.fillRect(10, 10, 50, 50);
缩放
- 使用 scale(xScale, yScale) 方法可以对图形进行缩放。
- xScale 和 yScale 分别表示在 x 轴和 y 轴上的缩放比例。
ctx.fillRect(10, 10, 50, 50);
ctx.scale(2, 2);
ctx.fillRect(10, 10, 50, 50);
线性渐变和径向渐变
线性渐变
- 使用 createLinearGradient(x1, y1, x2, y2) 方法创建一个线性渐变对象。这个方法接受四个参数,分别表示渐变的起始点坐标和结束点坐标。
var gradient = ctx.createLinearGradient(0, 0, 100, 0);
gradient.addColorStop(0, "red");
gradient.addColorStop(1, "blue");
径向渐变
使用 createRadialGradient(x1, y1, r1, x2, y2, r2) 方法创建一个径向渐变对象。这个方法接受六个参数,分别表示两个圆的圆心坐标和半径。
var gradient = ctx.createRadialGradient(50, 50, 10, 50, 50, 30);
gradient.addColorStop(0, "red");
gradient.addColorStop(1, "blue");
应用渐变到图形上
创建好渐变对象后,可以将其设置为 fillStyle 或 strokeStyle 属性的值,然后使用 fill() 或 stroke() 方法来绘制图形,就可以应用渐变效果了。
ctx.fillStyle = gradient;
ctx.fillRect(10, 10, 100, 100);
清除 Canvas 区域
ctx.clearRect(0, 0, canvas.width, canvas.height);
canvas 常用方法汇总
代码示例
canvas 展示图片
<template>
<div ref="app">
</div>
</template>
<script lang="ts" setup>
import {ref, onMounted} from "vue";
import imageSrc from "./assets/image.jpeg"
const app = ref()
const initCanvas = ()=> {
const imageRef = new Image()
imageRef.src = imageSrc
imageRef.onload = ()=>{
const width = imageRef.width
const height = imageRef.height
console.log("img", imageRef)
const canvasRef = document.createElement("canvas")
app.value.appendChild(canvasRef)
canvasRef.width = width;
canvasRef.height = height;
const ctx = canvasRef.getContext('2d')
ctx?.drawImage(imageRef, 0 ,0, width, height);
}
}
onMounted(() => {
initCanvas();
})
</script>
canvas 播放视频
<template>
<div ref="app">
</div>
</template>
<script lang="ts" setup>
import {ref, onMounted} from "vue";
const app = ref()
const initCanvas = async()=> {
let videoRef = document.createElement("video");
let videoWidth: number
let videoHeight:number
const canvasRef = document.createElement("canvas");
// 视频资源链接,需要保证该资源支持跨域
videoRef.src = "*****"
videoRef.muted = true
videoRef.controls = true;
videoRef.preload = 'auto';
videoRef.autoplay = true
videoRef.loop = true
videoRef.addEventListener("loadeddata", () => {
videoWidth = videoRef.videoWidth
videoHeight = videoRef.videoHeight
app.value.appendChild(canvasRef);
canvasRef.width = videoWidth;
canvasRef.height = videoHeight;
const ctx = canvasRef.getContext('2d')
videoRef.onerror = err => console.log(err)
videoRef.play().catch(err => console.log(err) )
const drawFrame = () => {
ctx?.drawImage(videoRef, 0, 0, canvasRef.width, canvasRef.height);
requestAnimationFrame(drawFrame)
}
drawFrame()
})
}
onMounted(() => {
initCanvas();
})
</script>