在网页网站日常开发中,我们通常用会用到图片展示、图片切片技术等手段来实现网页中图片的应用。
这可能是大多数人会想到的办法,那么还有其他的方式么?
这里来介绍一种新的实现方式,它的名字叫“Canvas”。
Canvas是一个HTML5元素,用于在网页上绘制图形、动画和其他可视化内容。它提供了一个JavaScript API,可以通过编程方式在Canvas上绘制各种图形,包括线条、矩形、圆形、文本等。Canvas非常灵活,可以用于创建各种交互式图表、游戏和图像处理应用程序等。您可以使用Canvas来实现各种创意和实用的功能,如绘制动态图形、处理用户输入、创建图表和数据可视化等。
优点:通过canvas展示图片或者图片可以节省大量网络流量
缺点:入门简单,但是对画图要有深刻理解,才能画出好图形
下面我来实现两个案例:
第一个就是实现画圆、画线、点击事件、放大缩小。具体实现效果如下:
画圆:
核心函数:arc
它有6个参数:
1.x 圆的中心的 x 坐标。
2.y 圆的中心的 y 坐标。
3.r 圆的半径。
4.sAngle 起始角,以弧度计(弧的圆形的三点钟位置是 0 度)。
5.eAngle 结束角,以弧度计。
6.counterclockwise 可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。
从中可以看的出来,它以x,y坐标为中心,r为半径向四周360度展开画图,类似于我们使用圆规的动作。
画线:
核心函数:moveTo,lineTo
它们两个都需要两个参数,分别都是x,y坐标值
moveTo作用就是把我们的画笔移动到x,y坐标,左上角0,0为起始位置。
lineTo作用就是画线,把从当前画笔位置移动我们画线的位置,中间形成的轨迹就是一条线。
点击事件
点击事件这里主要实现是通过监听canvas的画布的点击事件,判断当前点击位置是否处于所画的位置范围内。
放大缩小
核心函数:scale
scale函数使用来调整图形的放大和缩小
它有两个参数,分别是x
:横轴和y
:纵轴的缩放因子。x,y两个参数默认1,如果要放大就在x,y两个参数各自加+0.1,这样就实现了放大原来图形的十分之一。
下面我们来一份综合的实现案例:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas点击</title>
</head>
<body>
<div>
<button id="test">放大</button>
<button id="test2">缩小</button>
</div>
<canvas id="myCanvas" width="800" height="600" style="border:1px solid #000000;margin-top:10px"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const test = document.getElementById('test');
const test2 = document.getElementById('test2');
const ctx = canvas.getContext('2d');
// 绘制圆形
function drawCircle(x, y, radius, color) {
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fillStyle = color;//设置填充颜色
ctx.fill();//开始填充
ctx.stroke();
}
// 绘制线
function drawLine(startX, startY, endX, endY, color) {
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.lineTo(endX, endY);
if (color) {
color = color
} else {
ctx.strokeStyle = 'blue';
}
ctx.stroke();
}
// 检查点击位置是否在矩形内的函数
function isInsideRect(x, y, rect) {
return x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height;
}
// 添加放大缩小画布的方法
var zoom = 1;
function zoomBox() {
ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除画布
ctx.save(); // 保存当前状态
ctx.scale(zoom, zoom); // 缩放
draw()
ctx.restore(); // 恢复状态
}
function draw(params) {
drawCircle(100, 100, 10, 'green');
drawLine(110, 100, 200, 100)
drawCircle(210, 100, 10, 'green');
drawLine(210, 110, 210, 200)
drawCircle(210, 210, 10, 'green');
drawLine(220, 210, 300, 210)
drawCircle(310, 210, 10, 'green');
}
// 添加点击事件处理程序
canvas.addEventListener('click', function (event) {
const x = event.clientX - canvas.offsetLeft;
const y = event.clientY - canvas.offsetTop;
console.info("x", x, "y", y)
if (isInsideRect(x, y, { x: 90 * zoom, y: 90 * zoom, width: 20 * zoom, height: 20 * zoom })) {
alert("点击了第1个圆")
}
if (isInsideRect(x, y, { x: 110 * zoom, y: 100 * zoom, width: 100 * zoom, height: 5 * zoom })) {
alert("点击了第1个线")
}
if (isInsideRect(x, y, { x: 200 * zoom, y: 90 * zoom, width: 20 * zoom, height: 20 * zoom })) {
alert("点击了第2个圆")
}
if (isInsideRect(x, y, { x: 210 * zoom, y: 110 * zoom, width: 5 * zoom, height: 90 * zoom })) {
alert("点击了第2个线")
}
if (isInsideRect(x, y, { x: 200 * zoom, y: 200 * zoom, width: 20 * zoom, height: 20 * zoom })) {
alert("点击了第3个圆")
}
if (isInsideRect(x, y, { x: 220 * zoom, y: 210 * zoom, width: 85 * zoom, height: 5 * zoom })) {
alert("点击了第3个线")
}
if (isInsideRect(x, y, { x: 300 * zoom, y: 200 * zoom, width: 20 * zoom, height: 20 * zoom })) {
alert("点击了第4个圆")
}
});
test.addEventListener('click', function (event) {
zoom += 0.1
zoomBox()
});
test2.addEventListener('click', function (event) {
zoom -= 0.1
zoomBox()
});
draw()
</script>
</body>
</html>
通过了解原理我们可以实现画出各种各样的图形甚至图像的实现。
画一个笑脸
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas笑脸</title>
</head>
<body>
<canvas id="smileyCanvas" width="400" height="400"></canvas>
<script>
var canvas = document.getElementById('smileyCanvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
// 绘制脸部
ctx.beginPath();
ctx.arc(200, 200, 150, 0, Math.PI * 2, true); // 圆形脸
ctx.fillStyle = 'yellow';
ctx.fill();
ctx.stroke();
// 绘制左眼
ctx.beginPath();
ctx.arc(150, 150, 20, 0, Math.PI * 2, true); // 左眼
ctx.fillStyle = 'black';
ctx.fill();
// 绘制右眼
ctx.beginPath();
ctx.arc(250, 150, 20, 0, Math.PI * 2, true); // 右眼
ctx.fillStyle = 'black';
ctx.fill();
// 绘制微笑
ctx.beginPath();
ctx.arc(200, 220, 80, 0, Math.PI, false); // 半圆形微笑
ctx.stroke();
}
</script>
</body>
</html>
超萌小黑猫
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>猫猫</title>
</head>
<body>
<canvas id="myCanvas" width="610" height="430"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
// 绘制身体
// 左侧身体
ctx.beginPath();
// 手臂外侧
// 开始点
ctx.moveTo(275, 260);
// 控制点230,315 结束点 255,325
ctx.quadraticCurveTo(230, 315, 255, 325);
ctx.lineTo(270, 320);
// 手臂内侧
ctx.quadraticCurveTo(260, 310, 270, 280);
// 胳子窝
ctx.quadraticCurveTo(272, 275, 274, 280);
// 身体外侧
ctx.quadraticCurveTo(263, 300, 276, 330);
// 左腿外侧
ctx.lineTo(274, 355);
// 左脚
ctx.quadraticCurveTo(258, 370, 290, 372);
ctx.quadraticCurveTo(320, 375, 310, 348);
// 裆部
ctx.quadraticCurveTo(308, 338, 314, 346);
// 右侧身体
// 右脚
ctx.quadraticCurveTo(320, 362, 315, 364);
ctx.quadraticCurveTo(310, 372, 335, 373);
ctx.quadraticCurveTo(365, 370, 350, 350);
// 右脚尾巴连接处
ctx.lineTo(351, 335);
// 尾巴
ctx.quadraticCurveTo(390, 365, 420, 300);
ctx.quadraticCurveTo(430, 280, 400, 308);
ctx.quadraticCurveTo(385, 350, 352, 328);
// 身体外侧
ctx.quadraticCurveTo(365, 315, 354, 280);
// 胳子窝
ctx.quadraticCurveTo(352, 275, 358, 280);
// 手臂内侧
ctx.quadraticCurveTo(370, 305, 358, 325);
// 手臂外侧
ctx.quadraticCurveTo(370, 335, 382, 318);
ctx.quadraticCurveTo(390, 300, 342, 250);
ctx.closePath();
ctx.fillStyle = '#000';
ctx.fill();
// 脖子
ctx.beginPath();
ctx.ellipse(309, 253, 42, 25, 0, Math.PI * 0.9, Math.PI * 0.02, true);
ctx.fillStyle = '#87e5f1';
ctx.fill();
// 耳朵
// 绘制左耳
ctx.beginPath();
ctx.moveTo(235, 175);
ctx.quadraticCurveTo(185, 75, 272, 140);
ctx.closePath();
ctx.fillStyle = '#000';
ctx.fill();
// 左耳内
ctx.beginPath();
ctx.moveTo(237, 160);
ctx.quadraticCurveTo(207, 105, 255, 138);
ctx.closePath();
ctx.fillStyle = '#faf0bf';
ctx.fill();
// 绘制右耳
ctx.beginPath();
ctx.moveTo(338, 129);
ctx.quadraticCurveTo(415, 80, 375, 160);
ctx.closePath();
ctx.fillStyle = '#000';
ctx.fill();
// 右耳内
ctx.beginPath();
ctx.moveTo(343, 134);
ctx.quadraticCurveTo(400, 100, 370, 158);
ctx.closePath();
ctx.fillStyle = '#faf0bf';
ctx.fill();
// 胡须
// 绘制左侧胡须
ctx.beginPath();
ctx.moveTo(245, 210);
ctx.lineTo(190, 212);
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.stroke();
ctx.beginPath();
ctx.moveTo(255, 235);
ctx.lineTo(200, 255);
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.stroke();
// 绘制右侧胡须
ctx.beginPath();
ctx.moveTo(385, 210);
ctx.lineTo(420, 212);
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.stroke();
ctx.beginPath();
ctx.moveTo(375, 235);
ctx.lineTo(405, 250);
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.stroke();
// 眼睛嘴巴
// 绘制上半部分脸
ctx.beginPath();
ctx.arc(305, 200, 80, Math.PI * 0.9, Math.PI * 0.1);
ctx.fillStyle = '#000';
ctx.fill();
// 绘制下半部分脸
ctx.beginPath();
ctx.ellipse(305, 200, 82, 65, 0, Math.PI * 0.9, Math.PI * 0.1, true);
ctx.fillStyle = '#000';
ctx.fill();
// 绘制左眼
ctx.beginPath();
ctx.arc(270, 200, 20, 0, Math.PI * 2);
ctx.fillStyle = '#fff';
ctx.fill();
// 绘制左眼眼珠
ctx.beginPath();
ctx.arc(275, 200, 7, 0, Math.PI * 2);
ctx.fillStyle = '#000';
ctx.fill();
// 绘制右眼
ctx.beginPath();
ctx.arc(340, 200, 20, 0, Math.PI * 2);
ctx.fillStyle = '#fff';
ctx.fill();
// 绘制右眼眼珠
ctx.beginPath();
ctx.arc(335, 200, 7, 0, Math.PI * 2);
ctx.fillStyle = '#000';
ctx.fill();
// 绘制嘴巴
ctx.beginPath();
ctx.ellipse(307, 223, 10, 7, 0, 0, Math.PI * 2);
ctx.fillStyle = '#ff6600';
ctx.fill();
</script>
</body>
</html>
画flappy bird游戏动画
看到这个我突然觉得Canvas可以画万物了,只要敢想就没有画不出来的。^_^