html canvas 复制,小白可以看懂的H5 Canvas

20200123235304579s5a8z4m1gcswn4o_9.png

Canvas是常见的前端技术,但是由于API众多,使用复杂,且对程序员的数学功底、空间想象能力乃至审美都有一定要求,所以真正擅长canvas的前端并不多,但并不代表大家就学不好canvas。我在此将常用的canvas使用场景罗列出来希望能帮助到大家。

创建canvas

Canvas的创建很简单,只需要一个标签足以,而内部复杂的实现都交给浏览器搞定。

html:

所有的绘制动作都需要在canvas上下文(context)中进行,因此我们需要先创建一个上下文。

js:

const canvas = document.getElementById('canvas');

const ctx = canvas.getContext('2d');

设置canvas尺寸

js:

canvas.width = 600;

canvas.height = 600;

若要满屏显示可以:

canvas.width = window.innerWidth;

canvas.height = window.innerHeight;

绘制图形

一、矩形(Rect)

1、实心矩形(fillRect)

绘制实心矩形最简单的是用 fillRect(x, y, width, height) 方法,参数中 x, y 表示矩形左上角的坐标;width、height 分别表示矩形的宽、高。使用方法如下:

js:

// 设置填充颜色

ctx.fillStyle = 'skyblue';

// 绘制实心矩形

ctx.fillRect(20, 20, 150, 100);

效果:

20200123235304579s5a8z4m1gcswn4o_14.png

2、空心矩形(strokeRect)

与绘制实心矩形类似的是使用 strokeRect(x, y, width, height) 方法绘制空心矩形。参数与 fillText 方法一致。

js:

// 设置线宽

ctx.lineWidth = 5;

// 设置绘制颜色

ctx.strokeStyle = 'chocolate';

// 绘制空心矩形

ctx.strokeRect(20, 20, 150, 100);

效果:

20200123235304579s5a8z4m1gcswn4o_4.png

3、清空矩形区域(clearRect)

当要重绘canvas中的内容时(比如动画),我们需要先使用 clearRect(x, y, width, height) 清空canvas。

js:

ctx.fillStyle = 'skyblue';

ctx.fillRect(20, 20, 150, 100);

// 清除画布中的矩形区域

ctx.clearRect(25, 25, 140, 90);

效果:

20200123235304579s5a8z4m1gcswn4o_11.png

二、文字(Text)

1、实心文字(fillText)

绘制文字也是canvas的基本功能,实心文字可以使用 fillText(text, x, y [, maxWidth]) 方法,参数中 text 表示绘制的文字;x, y 为文字起点的坐标;maxWidth 为可选参数,表示文字的最大宽度,如果文字超过该最大宽度那么浏览器将会通过调整字间距、字体或者压缩文字来适应最大宽度。

js:

// 设置绘制颜色

ctx.fillStyle = 'purple';

// 设置字体

ctx.font = '30px Arial';

// 绘制实心颜色

ctx.fillText('Hello World', 220, 50);

效果:

20200123235304579s5a8z4m1gcswn4o_13.png

2、空心文字(strokeText)

类似的,空心文字可以使用 strokeText(text, x, y [, maxWidth]) 绘制,参数与 fillText 方法一致:

js:

// 设置线宽

ctx.lineWidth = 3;

// 设置文字颜色

ctx.strokeStyle = 'orange';

// 设置字体

ctx.font = '50px Arial';

// 绘制空心文字

ctx.strokeText('Hello World', 180, 50);

效果:

20200123235304579s5a8z4m1gcswn4o_2.png

三、路径(Path)

顾名思义,通过Path我们可以定义一段段路径(或直线、或曲线)来组合出我们想要的图形。

1. 矩形

使用Path也可以绘制矩形,和 fillRect、strokeRect一样的效果,但是多一个步骤。使用 rect(x, y, width, height) 方法可以向当前路径添加一个矩形,该方法只会改变路径但不会直接渲染出矩形,所以还需要执行 fill() 或 stroke() 方法:

js:

ctx.rect(200, 20, 200, 100);

ctx.fillStyle = 'deeppink';

ctx.fill();

效果:

20200123235304579s5a8z4m1gcswn4o_0.png

或者,空心矩形:

ctx.rect(200, 20, 200, 100);

ctx.lineWidth = 3;

ctx.strokeStyle = 'deeppink';

ctx.stroke();

效果:

20200123235304579s5a8z4m1gcswn4o_16.png

2、三角形

用路径可以绘制各种自定义的图形,比如三角形:

js:

// 开始绘制路径

ctx.beginPath();

// 移动至起点

ctx.moveTo(200, 20);

// 绘制线段

ctx.lineTo(300, 20);

ctx.lineTo(250, 150);

ctx.lineTo(200, 20);

// 绘制路径

ctx.stroke();

效果:

20200123235304579s5a8z4m1gcswn4o_15.png

或者在绘制最后一边的时候可以使用ctx.closePath(),使路径闭合。

我们也可以将闭合的路径填充颜色,以实现实心三角形的绘制:

js:

ctx.beginPath();

ctx.moveTo(200, 20);

ctx.lineTo(300, 20);

ctx.lineTo(250, 150);

// 闭合路径

ctx.closePath();

// 设置填充颜色

ctx.fillStyle = 'coral';

// 填充路径

ctx.fill();

效果:

20200123235304579s5a8z4m1gcswn4o_8.png

3、弧线

(1)标准圆弧

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();

效果:

20200123235304579s5a8z4m1gcswn4o_17.png

(2)二次方曲线

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();

效果:

20200123235304579s5a8z4m1gcswn4o_7.png

(3)贝塞尔曲线

类似的,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();

效果:

20200123235304579s5a8z4m1gcswn4o_5.png

四、图片(Image)

我们也可以将图片绘制到canvas上面,使用 drawImage() 方法。drawImage()方法有三个重载:

drawImage(image, dx, dy);

drawImage(image, dx, dy, dWidth, dHeight);

drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

各参数的含义为:

dx: 在canvas上水平方向绘制的起点

dy: 在canvas上垂直方向绘制的起点

dWidth: 在canvas上绘制图片的宽度

dHeight: 在canvas上绘制图片的高度

sx: 原始图片上水平方向裁剪的起点

sy: 原始图片上垂直方向裁剪的起点

sWidth: 原始图片上水平方向裁剪的宽度

sHeight: 原始图片上垂直方向裁剪的高度

前两个重载比较好理解,就是在canvas上绘制出完整的源图片,并且可以通过设置宽高控制图片的缩放。第三个重载即在canvas上绘制出源图片的一部分,可以形象表示为:

20200123235304579s5a8z4m1gcswn4o_6.jpg

图片源以 HTMLImageElement 为例,在canvas上绘制图片可以这么实现:

html:

source

js:

const image = document.getElementById('source');

image.addEventListener('load', e => {

ctx.drawImage(image, 50, 150, 500, 300);

});

效果:

20200123235304579s5a8z4m1gcswn4o_1.png

五、动画(Animation)

使用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();

效果:

1460000021644632

我们也可以给小球加上碰撞检测,让它在canvas里面来回弹:

js:

function update() {

...

if (circle.x + circle.size > canvas.width || circle.x - circle.size < 0) {

circle.dx *= -1;

}

requestAnimationFrame(update);

}

效果:

1460000021644635

或者我们可以实现用键盘控制圆的移动:

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();

效果:

1460000021644634

Canvas库

由于canvas非常的强大,但是API较为复杂,所以业界出现了很多基于canvas的库,让大家使用canvas更加简单,下面列出一些供大家选择:

关于canvas就给大家介绍到这里,希望有朝一日大家都能用canvas画出心中最美的风景!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值