Canvas是常见的前端技术,可是因为API众多,使用复杂,且对程序员的数学功底、空间想象能力乃至审美都有必定要求,因此真正擅长canvas的前端并很少,但并不表明你们就学很差canvas。我在此将经常使用的canvas使用场景罗列出来但愿能帮助到你们。html
Canvas的建立很简单,只须要一个<canvas>
标签足以,而内部复杂的实现都交给浏览器搞定。前端
html:程序员
<canvas id="canvas"></canvas>
全部的绘制动做都须要在canvas上下文(context)中进行,所以咱们须要先建立一个上下文。web
js:canvas
const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d');
除了2d
,上下文还能够设置为:webgl, webgl2, bitmaprenderer浏览器
js:网络
canvas.width = 600; canvas.height = 600;
若要满屏显示能够:ide
canvas.width = window.innerWidth; canvas.height = window.innerHeight;
fillRect
)绘制实心矩形最简单的是用 fillRect(x, y, width, height)
方法,参数中 x, y
表示矩形左上角的坐标;width
、height
分别表示矩形的宽、高。使用方法以下:学习
js:字体
// 设置填充颜色 ctx.fillStyle = 'skyblue'; // 绘制实心矩形 ctx.fillRect(20, 20, 150, 100);
效果:
strokeRect
)与绘制实心矩形相似的是使用 strokeRect(x, y, width, height)
方法绘制空心矩形。参数与 fillText
方法一致。
js:
// 设置线宽 ctx.lineWidth = 5; // 设置绘制颜色 ctx.strokeStyle = 'chocolate'; // 绘制空心矩形 ctx.strokeRect(20, 20, 150, 100);
效果:
clearRect
)当要重绘canvas中的内容时(好比动画),咱们须要先使用 clearRect(x, y, width, height)
清空canvas。
js:
ctx.fillStyle = 'skyblue'; ctx.fillRect(20, 20, 150, 100); // 清除画布中的矩形区域 ctx.clearRect(25, 25, 140, 90);
效果:
绘制文字也是canvas的基本功能,实心文字可使用 fillText(text, x, y [, maxWidth])
方法,参数中 text
表示绘制的文字;x, y
为文字起点的坐标;maxWidth
为可选参数,表示文字的最大宽度,若是文字超过该最大宽度那么浏览器将会经过调整字间距、字体或者压缩文字来适应最大宽度。
js:
// 设置绘制颜色 ctx.fillStyle = 'purple'; // 设置字体 ctx.font = '30px Arial'; // 绘制实心颜色 ctx.fillText('Hello World', 220, 50);
效果:
相似的,空心文字可使用 strokeText(text, x, y [, maxWidth])
绘制,参数与 fillText
方法一致:
js:
// 设置线宽 ctx.lineWidth = 3; // 设置文字颜色 ctx.strokeStyle = 'orange'; // 设置字体 ctx.font = '50px Arial'; // 绘制空心文字 ctx.strokeText('Hello World', 180, 50);
效果:
顾名思义,经过Path咱们能够定义一段段路径(或直线、或曲线)来组合出咱们想要的图形。
使用Path也能够绘制矩形,和 fillRect
、strokeRect
同样的效果,可是多一个步骤。使用 rect(x, y, width, height)
方法能够向当前路径添加一个矩形,该方法只会改变路径但不会直接渲染出矩形,因此还须要执行 fill()
或 stroke()
方法:
js:
ctx.rect(200, 20, 200, 100); ctx.fillStyle = 'deeppink'; ctx.fill();
效果:
或者,空心矩形:
ctx.rect(200, 20, 200, 100); ctx.lineWidth = 3; ctx.strokeStyle = 'deeppink'; ctx.stroke();
效果:
用路径能够绘制各类自定义的图形,好比三角形:
js:
// 开始绘制路径 ctx.beginPath(); // 移动至起点 ctx.moveTo(200, 20); // 绘制线段 ctx.lineTo(300, 20); ctx.lineTo(250, 150); ctx.lineTo(200, 20); // 绘制路径 ctx.stroke();
效果:
或者在绘制最后一边的时候可使用ctx.closePath()
,使路径闭合。
咱们也能够将闭合的路径填充颜色,以实现实心三角形的绘制:
js:
ctx.beginPath(); ctx.moveTo(200, 20); ctx.lineTo(300, 20); ctx.lineTo(250, 150); // 闭合路径 ctx.closePath(); // 设置填充颜色 ctx.fillStyle = 'coral'; // 填充路径 ctx.fill();
效果:
Canvas中没有专门绘制圆的方法,而是使用更加通用的方法arc(x, y, radius, startAngle, endAngle [, anticlockwise])
绘制弧线,参数中 x, y
为圆心坐标;radius
为圆的半径; startAngle
为弧的初始角度;endAngle
为弧的结束角度;anticlockwise
表示是否以逆时针方向绘制路径。例如绘制圆,能够写成:
js:
ctx.beginPath(); ctx.arc(300, 300, 60, 0, Math.PI * 2, true); ctx.stroke();
效果:
Canvas也支持绘制二次方曲线,使用 quadraticCurveTo(cpx, cpy, x, y)
方法,参数为两个点的坐标,其中 cpx, cpy
为控制点的坐标;x, y
为结束点的坐标。使用方法以下:
js:
ctx.beginPath(); ctx.moveTo(150, 400); ctx.quadraticCurveTo(300, 0, 450, 400); ctx.stroke();
效果:
相似的,canvas还支持绘制常见的贝塞尔曲线,使用 bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
,参数中 cp1x, cp1y
为第一控制点的坐标;cp2x, cp2y
为第二控制点的坐标;x, y
为结束点的坐标。一个简单的贝塞尔曲线能够表示以下:
js:
ctx.beginPath(); ctx.moveTo(100, 400); ctx.bezierCurveTo(200, 200, 400, 400, 500, 200); ctx.stroke();
效果:
咱们也能够将图片绘制到canvas上面,使用 drawImage()
方法。drawImage()
方法有三个重载:
drawImage(image, dx, dy); drawImage(image, dx, dy, dWidth, dHeight); drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
各参数的含义为:
image: 被绘制到canvas上面的图片源,支持多种类型:CSSImageValue, HTMLImageElement, SVGImageElement, HTMLVideoElement, HTMLCanvasElement, ImageBitmap, OffscreenCanvas
dx: 在canvas上水平方向绘制的起点
dy: 在canvas上垂直方向绘制的起点
dWidth: 在canvas上绘制图片的宽度
dHeight: 在canvas上绘制图片的高度
sx: 原始图片上水平方向裁剪的起点
sy: 原始图片上垂直方向裁剪的起点
sWidth: 原始图片上水平方向裁剪的宽度
sHeight: 原始图片上垂直方向裁剪的高度
前两个重载比较好理解,就是在canvas上绘制出完整的源图片,而且能够经过设置宽高控制图片的缩放。第三个重载即在canvas上绘制出源图片的一部分,能够形象表示为:
图片源以 HTMLImageElement
为例,在canvas上绘制图片能够这么实现:
html:
<img id="source" style="display: none;" src="https://unsplash.it/500/300?image=1074" alt="source">
js:
const image = document.getElementById('source'); image.addEventListener('load', e => { ctx.drawImage(image, 50, 150, 500, 300); });
效果:
使用canvas配合 requestAnimationFrame 能够很方便的实现一些动画效果,好比实现一个圆从左往右移动的动画:
js:
/** * 定义圆 */ const circle = { x: 30, // 水平方向的坐标 y: 300, // 垂直方向的坐标 size: 30, // 圆的半径 dx: 5, // 水平坐标的变化值 dy: 4 // 垂直坐标的变化值 } /** * 绘制圆 */ function drawCirle() { ctx.beginPath(); ctx.arc(circle.x, circle.y, 30, 0, Math.PI * 2); ctx.fillStyle = 'purple'; ctx.fill(); } /** * 更新canvas实现动画效果 */ function update() { ctx.clearRect(0, 0, canvas.width, canvas.height); drawCirle(); circle.x += circle.dx; requestAnimationFrame(update); } update();
效果:
咱们也能够给小球加上碰撞检测,让它在canvas里面来回弹:
js:
function update() { ... if (circle.x + circle.size > canvas.width || circle.x - circle.size < 0) { circle.dx *= -1; } requestAnimationFrame(update); }
效果:
或者咱们能够实现用键盘控制圆的移动:
js:
/** * 定义圆 */ const circle = { x: 300, // 水平方向的坐标 y: 300, // 垂直方向的坐标 size: 30, // 圆的半径 dx: 0, // 水平坐标的变化值 dy: 0, // 垂直坐标的变化值 speed: 10 // 移动速度 } /** * 绘制圆 */ function drawCirle() { ctx.beginPath(); ctx.arc(circle.x, circle.y, 30, 0, Math.PI * 2); ctx.fillStyle = 'purple'; ctx.fill(); } /** * 更新canvas实现动画效果 */ function update() { ctx.clearRect(0, 0, canvas.width, canvas.height); circle.x += circle.dx; circle.y += circle.dy; // 边界碰撞检测 const leftMost = circle.size; const rightMost = canvas.width - circle.size; const topMost = circle.size; const bottomMost = canvas.height - circle.size; if (circle.x < leftMost) { circle.x = leftMost; } if (circle.x > rightMost) { circle.x = rightMost; } if (circle.y < topMost) { circle.y = topMost; } if (circle.y > bottomMost) { circle.y = bottomMost; } // 绘制圆 drawCirle(); requestAnimationFrame(update); } /** * 开始移动 */ function move(e) { const { key } = e; if (key === 'ArrowUp' || key === 'Up') { circle.dy = -circle.speed; } else if (key === 'ArrowDown' || key === 'Down') { circle.dy = circle.speed; } else if (key === 'ArrowLeft' || key === 'Left') { circle.dx = -circle.speed; } else if (key === 'ArrowRight' || key === 'Right') { circle.dx = circle.speed; } } /** * 中止移动 */ function stop(e) { if ( e.key == 'Right' || e.key == 'ArrowRight' || e.key == 'Left' || e.key == 'ArrowLeft' || e.key == 'Up' || e.key == 'ArrowUp' || e.key == 'Down' || e.key == 'ArrowDown' ) { circle.dx = 0; circle.dy = 0; } } document.addEventListener('keydown', move); document.addEventListener('keyup', stop); update();
效果:
因为canvas很是的强大,可是API较为复杂,因此业界出现了不少基于canvas的库,让你们使用canvas更加简单,下面列出一些供你们选择:
关于canvas就给你们介绍到这里,但愿有朝一日你们都能用canvas画出心中最美的风景!