HTML画布标签
在学习画布标签之前,需要对 ”CSS 样式 + JavaScript 行为“ 有一定的了解,这样才具备 Canvas 画布标签 API 的使用能力,Canvas 通过 JavaScript 对其 API 的引用处理
<canvas>
标签用于定义图形容器,容器本身是没有画图能力的,但我们可以使用脚本来绘制图形
创建画布
一个画布在网页中是一个矩形框,通过 <canvas>
元素来绘制,默认情况下 <canvas>
元素没有边框和内容,通过 style
样式定义边框
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>画布标签</title>
</head>
<body>
<canvas id="canvas" width="200" height="100" style="border:1px solid #000;"></canvas>
</body>
</html>
尝试通过 style
来给画布定义一个红色背景
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>画布标签</title>
</head>
<body>
<canvas id="canvas" width="200" height="100" style="border:1px solid #000; background-color: #f00;"></canvas>
</body>
</html>
如果不让画布的背景全部为红色,而是改成四分之一变成红色,这里就需要通过画布填充来实现啦
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>画布标签</title>
</head>
<body>
<canvas id="canvas" width="200" height="100" style="border:1px solid #000;"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var contxt = canvas.getContext('2d');
contxt.fillStyle="#ff0000";
contxt.fillRect(0, 0, 100, 50);
</script>
</body>
</html>
- fillStyle 设置画布的填充颜色、渐变、图案,默认为 #000000
- fillRect 设置画布的填充矩形对角坐标,前两个值为起始坐标点,后两个值为对角坐标点
绘制路径
在Canvas上画线,我们将使用以下两种方法:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>画布标签</title>
</head>
<body>
<canvas id="canvas" width="200" height="100" style="border:1px solid #000;"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var contxt = canvas.getContext('2d');
contxt.moveTo(0, 0);
contxt.lineTo(200, 100);
contxt.stroke();
</script>
</body>
</html>
- moveTo(x, y) 定义线条开始坐标
- lineTo(x, y) 定义线条结束坐标
- stroke() 表示执行划线操作
- strokeStyle 定义画笔的颜色
- arc() 定义圆形弧盘
- arcTo() 自定义弧线走势
通过重复 moveTo
组合 lineTo
绘制多条线条,如下画两条红色的平行线
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>画布标签</title>
</head>
<body>
<canvas id="canvas" width="200" height="100" style="border:1px solid #000;"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var contxt = canvas.getContext('2d');
contxt.moveTo(0, 0);
contxt.lineTo(200, 100);
contxt.moveTo(0, 50);
contxt.lineTo(200, 150);
contxt.strokeStyle = '#ff0000';
contxt.stroke();
</script>
</body>
</html>
arc
前两个参数值表示圆心坐标,第三个值为圆半径,第四、五个值为起始、结束弧度,第六个值布尔类型值,true 表示逆时针画弧,false 表示顺时针画弧
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>画布标签</title>
</head>
<body>
<canvas id="canvas" width="200" height="100" style="border:1px solid #000;"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var contxt = canvas.getContext('2d');
contxt.arc(100, 50, 40, 0, 2 * Math.PI);
contxt.stroke();
</script>
</body>
</html>
arcTo
前两个表示起始坐标,第三、四个表示结束坐标,第五个值表示画弧半径
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>画布标签</title>
</head>
<body>
<canvas id="canvas" width="200" height="100" style="border:1px solid #000;"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var contxt = canvas.getContext('2d');
contxt.moveTo(50, 50);
contxt.arcTo(200, 50, 200, 200, 100);
contxt.lineTo(200, 200);
contxt.stroke();
</script>
</body>
</html>
绘制文本
使用 canvas 绘制文本,重要的属性和方法如下:
- font - 定义字体
- fillText(text, x, y) - 在 canvas 上绘制实心的文本
- strokeText(text, x, y) - 在 canvas 上绘制空心的文本
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>画布标签</title>
</head>
<body>
<canvas id="canvas" width="200" height="100" style="border:1px solid #000;"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var contxt = canvas.getContext('2d');
contxt.font = "14px Arial";
contxt.fillText("好好学习", 10, 20);
contxt.strokeText("天天向上", 10, 40);
</script>
</body>
</html>
绘制渐变
渐变可以填充在矩形, 圆形, 线条, 文本等等, 各种形状可以自己定义不同的颜色。
以下有两种不同的方式来设置Canvas渐变:
- createLinearGradient(x, y, x1, y1) - 创建线条渐变
- createRadialGradient(x, y, r, x1, y1, r1) - 创建一个径向/圆渐变
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>画布标签</title>
</head>
<body>
<canvas id="canvas" width="200" height="100" style="border:1px solid #000;"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var contxt = canvas.getContext('2d');
var gradit = contxt.createLinearGradient(0, 0, 200, 0);
gradit.addColorStop(0, "#ff0000");
gradit.addColorStop(1, "#ffffff");
contxt.fillStyle = gradit;
contxt.fillRect(10, 10, 150, 80);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>画布标签</title>
</head>
<body>
<canvas id="canvas" width="200" height="100" style="border:1px solid #000;"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var contxt = canvas.getContext('2d');
var gradit = contxt.createRadialGradient(75, 50, 5, 90, 60, 100);
gradit.addColorStop(0, "#ff0000");
gradit.addColorStop(1, "#ffffff");
contxt.fillStyle = gradit;
contxt.fillRect(10, 10, 150, 80);
</script>
</body>
</html>
绘制图像
把一幅图像放置到画布上, 使用以下方法:
- drawImage(image, x, y)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>画布标签</title>
</head>
<body>
<p>Image to use:</p>
<img id="scream" src="https://www.runoob.com/try/demo_source/img_the_scream.jpg" alt="The Scream" width="220" height="277" />
<p>Canvas:</p>
<canvas id="canvas" width="250" height="300" style="border:1px solid #000;"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var contxt = canvas.getContext('2d');
var images = document.getElementById("scream");
images.onload = () => contxt.drawImage(images, 10, 10);
</script>
</body>
</html>
画布实战
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>画布标签</title>
<style type="text/css">
body {
padding: 0;
margin: 0;
background-color: rgba(0, 0, 0, 0.1)
}
canvas {
display: block;
margin: 50px auto;
}
</style>
</head>
<body>
<canvas id="canvas" width="300" height="300"></canvas>
<script type="text/javascript">
/*绘制表盘*/
const drawDial = (ctx) => {
let pi = Math.PI;
ctx.clearRect(0, 0, 300, 300); //清除所有内容
ctx.save();
ctx.translate(150, 150); //一定坐标原点到原来的中心
ctx.beginPath();
ctx.arc(0, 0, 148, 0, 2 * pi); //绘制圆周
ctx.stroke();
ctx.closePath();
for (let i = 0; i < 60; i++) {//绘制刻度。
ctx.save();
ctx.rotate(-pi / 2 + i * pi / 30); //旋转坐标轴。坐标轴x的正方形从 向上开始算起
ctx.beginPath();
ctx.moveTo(110, 0);
ctx.lineTo(140, 0);
ctx.lineWidth = i % 5 ? 2 : 4;
ctx.strokeStyle = i % 5 ? "blue" : "red";
ctx.stroke();
ctx.closePath();
ctx.restore();
}
ctx.restore();
}
/*绘制时针、或分针、或秒针
* 参数1:要绘制的针的角度
* 参数2:要绘制的针的长度
* 参数3:要绘制的针的宽度
* 参数4:要绘制的针的颜色
* 参数4:ctx
* */
const drawHand = (angle, len, width, color, ctx) => {
ctx.save();
ctx.translate(150, 150); //把坐标轴的远点平移到原来的中心
ctx.rotate(-Math.PI / 2 + angle); //旋转坐标轴。 x轴就是针的角度
ctx.beginPath();
ctx.moveTo(-4, 0);
ctx.lineTo(len, 0); // 沿着x轴绘制针
ctx.lineWidth = width;
ctx.strokeStyle = color;
ctx.lineCap = "round";
ctx.stroke();
ctx.closePath();
ctx.restore();
}
/*绘制时分秒针*/
const drawAllHands = (ctx) => {
let time = new Date();
let s = time.getSeconds();
let m = time.getMinutes();
let h = time.getHours();
let pi = Math.PI;
let secondAngle = pi / 180 * 6 * s; //计算出来s针的弧度
let minuteAngle = pi / 180 * 6 * m + secondAngle / 60; //计算出来分针的弧度
let hourAngle = pi / 180 * 30 * h + minuteAngle / 12; //计算出来时针的弧度
drawHand(hourAngle, 60, 6, "red", ctx); //绘制时针
drawHand(minuteAngle, 106, 4, "green", ctx); //绘制分针
drawHand(secondAngle, 129, 2, "blue", ctx); //绘制秒针
}
const draw = (ctx) => {
requestAnimationFrame(function step() {
drawDial(ctx); //绘制表盘
drawAllHands(ctx); //绘制时分秒针
requestAnimationFrame(step);
});
}
var canvas = document.getElementById('canvas');
var contxt = canvas.getContext('2d');
draw(contxt);
</script>
</body>
</html>