想象一下,用几行代码就能创造出如此逼真的图像和动画,仿佛将艺术与科技完美融合,前端开发的Canvas技术正是这个数字化时代中最具魔力的一环,它不仅仅是网页的一部分,更是一个无限创意的画布,一个让你的想象力自由驰骋的平台。
目录
颜色样式设置
线条样式设置
图像样式设置
文字样式设置
颜色样式设置
设置基础样式:除了绘制简单的图形,填充线条的样式外,我们还可以给图形进行一个上色处理,对颜色样式进行一个简单的设置,如果我们可以设置一下线条的颜色:
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
let heartPath = new Path2D();
// 初始起点
heartPath.moveTo(300, 200)
heartPath.bezierCurveTo(350, 150, 400, 200, 300, 300);
heartPath.bezierCurveTo(200, 200, 250, 150, 300, 200);
// 设置线条为红色,支持16进制,rgb(a) 等格式
ctx.strokeStyle='red';
ctx.stroke(heartPath)
let chatPath = new Path2D();
chatPath.moveTo(200, 300)
chatPath.quadraticCurveTo(150, 300, 150, 200);
chatPath.quadraticCurveTo(150, 100, 300, 100);
chatPath.quadraticCurveTo(450, 100, 450, 200);
chatPath.quadraticCurveTo(450, 300, 250, 300);
chatPath.quadraticCurveTo(250, 350, 150, 350);
chatPath.quadraticCurveTo(200, 350, 200, 300);
ctx.strokeStyle='blue';
ctx.stroke(chatPath)
</script>
</body>
得到的效果如下所示:
设置渐变样式:如果想设置渐变的样式的话,可以通过调用createLinearGradient函数创建
1)线性渐变:后添加在0-1之间的某个数值点位上设置颜色,从开始坐标到结束坐标进行颜色样式的渐变效果展示,代码示例如下:
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
// 绘制矩形
let linearGradient = ctx.createLinearGradient(100, 200, 400, 500); // 创建线性渐变
linearGradient.addColorStop(0, "red"); // 添加颜色 从第一个坐标开始
linearGradient.addColorStop(0.5, "yellow"); // 添加颜色 从中间开始
linearGradient.addColorStop(1, "blue"); // 添加颜色 从最后一个坐标结束
ctx.fillStyle = linearGradient; // 设置填充样式
ctx.fillRect(100, 200, 300, 300);
</script>
</body>
最终得到的结果如下所示:
当然如果想看到渐变效果动态的变化,没问题,这里我们设置一下渲染函数,动态的改变某一位置的颜色渐变效果,示例代码如下:
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
let index = 0;
function render() {
// 把上一次的绘制结果清除
ctx.clearRect(0, 0, 600, 400);
index += 0.01
if (index > 1) {
index = 0;
}
let linearGradient = ctx.createLinearGradient(100, 200, 400, 500); // 创建线性渐变
linearGradient.addColorStop(0, "red"); // 添加颜色 从第一个坐标开始
linearGradient.addColorStop(index, "#008c8c"); // 添加颜色 从中间开始
linearGradient.addColorStop(1, "blue"); // 添加颜色 从最后一个坐标结束
ctx.fillStyle = linearGradient; // 设置填充样式
ctx.fillRect(100, 200, 300, 300);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
</script>
</body>
最终呈现的效果如下所示:
2)镜像渐变:如果想创建镜像渐变的话,可以通过两个坐标表示内外圆,然后设置渐变效果,示例代码如下:
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
// 绘制圆
/*
参数依次是 (x0, y0, r0, x1, y1, r1),表示两个圆之间的渐变。在这里:
(300, 200, 0) 表示内圆的中心坐标 (x0, y0) 是 (300, 200),半径 r0 是 0,即一个点。
(300, 200, 100) 表示外圆的中心坐标 (x1, y1) 是 (300, 200),半径 r1 是 100。
*/
let radiaGradient = ctx.createRadialGradient(300, 200, 0, 300, 200, 100);
radiaGradient.addColorStop(0, 'red');
radiaGradient.addColorStop(0.3, '#ffcccc');
radiaGradient.addColorStop(1, 'blue');
ctx.fillStyle = radiaGradient;
ctx.fillRect(0, 0, 600, 400);
</script>
</body>
最终呈现的效果如下所示:
当然这里我们可以通过设置俩个球心,实现一个3d地球的效果,示例代码如下:
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
// 绘制圆
let radiaGradient = ctx.createRadialGradient(250, 150, 10, 300, 200, 100);
radiaGradient.addColorStop(0, '#fff');
radiaGradient.addColorStop(1, 'blue');
ctx.fillStyle = radiaGradient;
ctx.arc(300, 200, 100, 0, Math.PI * 2); // 绘制圆
ctx.fill() // 填充
</script>
</body>
最终呈现的效果如下:
3)圆锥渐变:如果想实现圆锥渐变的话,可以使用createConicGradient函数进行操作,示例代码如下:
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
// 绘制扇形渐变
let coneGradient = ctx.createConicGradient(0, 300, 200);
coneGradient.addColorStop(0, 'red');
coneGradient.addColorStop(1, 'blue');
ctx.fillStyle = coneGradient;
ctx.fillRect(0, 0, 600, 400) // 填充
</script>
</body>
最终呈现的效果如下所示:
线条样式设置
在上面我们讲解到了canvas的颜色样式的设置,那么如果我们想对canvas的线条进行一个样式的修改应该如何操作呢?这里开始进行一个简单的讲述,给出如下场景的修改线条样式的函数:
lineWidth = value:设置线条宽度。代码如下:
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
// 设置线条
function draw() {
for (let i = 0; i < 10; i++) {
ctx.lineWidth = i + 1;
ctx.beginPath(); // 开始一条新路径
ctx.moveTo(5+i*14, 5); // 移动到起点
ctx.lineTo(5+i*14, 140) // 绘制一条到终点
ctx.stroke();
}
}
draw();
</script>
</body>
线宽是指给定路径的中心到两边的粗细。换句话说就是在路径的两边各绘制线宽的一半,因为画布的坐标并不和像素直接对应,当需要获得精确的水平或垂直线的时候要特别注意。
lineCap = type:设置线条末端样式。代码如下:
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
// 设置线条
function draw() {
var lineCap = ['butt', 'round', 'square'];
// 创建路径
ctx.strokeStyle = '#09f';
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(140, 10);
ctx.moveTo(10, 140);
ctx.lineTo(140, 140);
ctx.stroke();
// 画线条
ctx.strokeStyle = 'black';
for (var i = 0; i < lineCap.length; i++) {
ctx.lineWidth = 15;
ctx.lineCap = lineCap[i];
ctx.beginPath();
ctx.moveTo(25 + i * 50, 10);
ctx.lineTo(25 + i * 50, 140);
ctx.stroke();
}
}
draw();
</script>
</body>
这里绘制了三条直线,分别赋予不同的 lineCap 值,还有两条辅助线,为了可以看得更清楚它们之间的区别,三条线的起点终点都落在辅助线上。最左边的线用了默认的 butt 。可以注意到它是与辅助线齐平的。中间的是 round 的效果,端点处加上了半径为一半线宽的半圆。右边的是 square 的效果,端点处加上了等宽且高度为一半线宽的方块:
lineJoin = type:设置线条与线条间接接合处的样式。代码如下:
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
// 设置线条
function draw() {
var lineJoin = ['round', 'bevel', 'miter'];
ctx.lineWidth = 10;
for (var i = 0; i < lineJoin.length; i++) {
ctx.lineJoin = lineJoin[i];
ctx.beginPath();
ctx.moveTo(-5, 5 + i * 40);
ctx.lineTo(35, 45 + i * 40);
ctx.lineTo(75, 5 + i * 40);
ctx.lineTo(115, 45 + i * 40);
ctx.lineTo(155, 5 + i * 40);
ctx.stroke();
}
}
draw();
</script>
</body>
这里用三条折线来做例子,分别设置不同的 lineJoin 值。最上面一条是 round 的效果,边角处被磨圆了,圆的半径等于线宽。中间和最下面一条分别是 bevel 和 miter 的效果。当值是 miter 的时候,线段会在连接处外侧延伸直至交于一点:
setLineDash(segments):设置当前虚线样式。代码如下:
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
// 设置线条
ctx.moveTo(150, 150)
ctx.lineTo(300, 200)
ctx.lineTo(450, 150)
// 设置虚线
ctx.setLineDash([10, 20])
ctx.stroke()
</script>
</body>
setLineDash 方法接受一个数组,来指定线段与间隙的交替:
lineDashOffset = value:设置当前虚线样式的起始偏移量。
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
// 设置线条
let index = 0
function render() {
ctx.clearRect(0, 0, 600, 400);
index++
if (index > 40) {
index = 0
}
ctx.moveTo(150, 150)
ctx.lineTo(300, 200)
ctx.lineTo(450, 150)
// 设置虚线
ctx.setLineDash([40, 20])
// 设置偏移量
ctx.lineDashOffset = index
ctx.stroke()
requestAnimationFrame(render) // 动画渲染
}
render()
</script>
</body>
设置线条的移动:
shadowOffsetX、shadowOffsetY、shadowBlur、shadowColor:设置阴影。代码如下:
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
// 设置线条
let index = 0
function render() {
ctx.clearRect(0, 0, 600, 400);
index++
if (index > 40) {
index = 0
}
ctx.moveTo(150, 150)
ctx.lineTo(300, 200)
ctx.lineTo(450, 150)
// 设置阴影
ctx.shadowOffsetX = 10 // 阴影偏移量
ctx.shadowOffsetY = 10 // 阴影偏移量
ctx.shadowBlur = 5 // 阴影模糊度
ctx.shadowColor = "rgba(255, 100, 10, 1)" // 阴影颜色
// 设置虚线
ctx.setLineDash([40, 20])
// 设置偏移量
ctx.lineDashOffset = index
ctx.stroke()
requestAnimationFrame(render) // 动画渲染
}
render()
</script>
</body>
效果如下:
图像样式设置
canvas更有意思的一项特性就是图像操作能力,可以用于动态的图像合成或者作为图形的背景,以及游戏界面(Sprites)等等。浏览器支持的任意格式的外部图片都可以使用,比如 PNG、GIF 或者JPEG,你甚至可以将同一个页面中其他 canvas 元素生成的图片作为图片源。
patterns图案填充:在上面我们讲解到了对画面进行一个颜色的填充,把画面填充成某一个固定的颜色或者说是一个渐变的颜色,那如果我想填充的不是渐变的颜色,而是一个个图像呢?这里我们就需要借助patterns这个属性来实现了,如下给出示例代码:
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
// 创建图案样式
let img = new Image();
img.src = "./1.jpg"
// 加载图片
img.onload = function(){
// 创建图案对象 createPattern(图片对象, 重复方式)
let pattern = ctx.createPattern(img, "repeat");
ctx.fillStyle = pattern;
ctx.fillRect(0, 0, 600, 400);
}
</script>
</body>
最终呈现的效果如下所示:
drawImage:对图片进行缩放,裁剪操作:
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
// 创建图案样式
let img = new Image();
img.src = "./1.jpg"
// 加载图片
img.onload = function(){
// 第一种绘制图片方式:参数是:图片资源,以及水平和垂直位置
// ctx.drawImage(img, 0, 0)
// 第二种绘制图片方式:参数是:图片资源,以及水平和垂直位置,以及缩放宽高600和400
// ctx.drawImage(img, 0, 0, 600, 400)
// 第三种绘制图片方式:参数是:图片资源,以及裁剪的起点位置和矩形宽高,以及裁剪以及水平和垂直位置,以及缩放宽高600和400
ctx.drawImage(img, 1040, 100, 1500, 720, 0, 0, 600, 400)
}
</script>
</body>
最终呈现的效果如下所示:
当然drawImage函数也是可以对视频进行相应操作的,这里简单赘述一下,示例代码如下:
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<video src="./1.mp4" controls style="width: 400px; height: auto;" hidden></video>
<button id="btn">播放 / 暂停</button>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
// 设置图像视频
let video = document.querySelector("video");
video.src = "./1.mp4";
let btn = document.getElementById("btn");
btn.onclick = function () {
if (video.paused) {
video.play();
render();
} else {
video.pause();
}
}
// 添加logo
let img = new Image();
img.src = "./1.jpg";
// 渲染函数
function render() {
ctx.drawImage(video, 0, 0, 600, 400); // 绘制视频
ctx.drawImage(img, 500, 350, 100, 50); // 绘制logo
requestAnimationFrame(render);
}
</script>
</body>
效果如下:
文字样式设置
canvas提供了两种方法来渲染文本,这里做一个简单的介绍,如下:
fillText(text, x, y [, maxWidth]):在指定的 (x,y) 位置填充指定的文本,绘制的最大宽度是可选的。代码如下:
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
// 设置文字
ctx.font = "30px Arial";
// 设置填充渲染文字
ctx.fillText("Hello World", 10, 30);
</script>
</body>
strokeText(text, x, y [, maxWidth]):在指定的 (x,y) 位置绘制文本边框,绘制的最大宽度是可选的。代码如下:
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
let canvas = document.getElementById("canvas");
// 获取2维画笔,上下文对象
let ctx = canvas.getContext("2d");
// 设置文字
ctx.font = "30px Arial";
// 设置文字颜色
ctx.strokeStyle='red';
// 设置文本对齐方式, 默认是 left
ctx.textAlign = "center";
// 设置基线对齐方式, 默认是 top
ctx.textBaseline = "middle";
// 设置文本方向,默认是 ltr
ctx.direction = "rtl";
// 设置填充渲染文字
ctx.strokeText("Hello World!", 300, 200);
</script>
</body>
上面代码同时给出了常用的文字操作方式,这里做一个简单的举例,最终得到的效果如下: