利用 HTML5
中的 Canvas
,我们可以做很多很棒的事情,下面来看看我做的一个 Demo
下面就针对这个例子介绍一下 Canvas
的基础使用。
HTML & CSS
当然 Canvas
的绘制需要借助 JavaScript
, 首先让我们利用 HTML
和 CSS
将结构层和表现层搭建好,然后我们才可以大展身手。
你可以利用自己高超的 CSS
水平将页面写的十分炫酷,当然我只是简单的利用 CSS
对页面进行了布局,没有写其它用来表现的特性。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="demo05.css">
</head>
<body>
<article>
<canvas width="680" height="320" id="myCanvas"></canvas>
<form>
<section>
<label for="backgroundColor">Select background :</label>
<select id="backgroundColor">
<option value="white" selected>White</option>
<option value="black">Black</option>
</select>
</section>
<section>
<label for="foregroundColor">Select ForegroundColor:</label>
<select id="foregroundColor">
<option value="white">White</option>
<option value="black" selected>Black</option>
</select>
</section>
<section>
<label for="shape">Select shape:</label>
<select id="shape">
<option value="circles" selected>Circles</option>
<option value="squares">Squares</option>
</select>
</section>
<section>
<label for="message">Input text:</label>
<input type="text" name="message" id="message" maxlength="48">
</section>
<input type="button" value="preview" id="previewButton">
</form>
</article>
<script src="demo05.js"></script>
</body>
</html>
其实大部分内容都是关于书写表单控件的,这些代码千篇一律,十分好懂,不过唯一值得注意的是,我在输入控件中加入了 maxlength
, 对输入的长度进行了控制,如果输入的字符串太多,绘制文字的时候会出现文字溢出。
上述代码中最珍贵的一行是定义 canvas
元素的那一行,将画布定义为 680px 宽,320px 高。
下面利用 CSS
对页面进行稍微的修改。
*,
*::before,
*::after {
-moz-box-sizing: border-box;
box-sizing: border-box;
margin: 0;
padding: 0;
}
article {
width: 680px;
height: 320px;
margin: 32px auto;
text-align: center;
}
canvas {
border: 1px solid #ccc;
}
form section {
margin-bottom: 16px;
}
这里,为画布设置了一个边框,是为了更清楚的看到画布的位置。
Canvas 绘图
为了绘制图形,我们首先要得到画布元素,并要求得到它的 2d 绘制上下文。像下面这样。
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
有了这个 context
, 我们就可以肆意的画图了,首先,让我们来画个矩形吧,需要哪些条件呢?事实上,我们只需要指定 x,y 坐标(矩形左上角的坐标)并且设置宽高就可以画出这个图形。
function drawSquare(canvas, context) {
var width = Math.floor(Math.random() * 64);
var x = Math.floor(Math.random() * canvas.width);
var y = Math.floor(Math.random() * canvas.height);
context.fillStyle = "lightblue";
context.fillRect(x, y, width, width);
}
上面我们使用了随机值,这样我们就可以绘制出不同宽高分布在不同位置的矩形了。利用上面的代码,我们就可以看到下面这样的结果啦。
可以看到,有的矩形已经超出边界了,为什么呢?自己好好想想总会相处答案的吧!
既然已经知道怎么绘制矩形了,那么该怎么绘制圆形呢?我已经迫不及待的去画个圆了,因为我感觉圆比矩形好看,这也就是为什么我们在很多 app 中看到的是圆形头像。
不过,事情进展的不是很顺利,因为我们已经没有类似 fillCircle()
这样的函数可用了。所以我们不得不动笔去画一个,实际上利用 Canvas
你可以画出可以用笔画出的任何效果。在现实生活中,如果你想画画,那么你需要拿起一支笔,但是在画布上,你只需要调用 context
的 beginPath()
方法就可以了,这相当于告诉画布:我要开始画些东西了,你准备好吧!
如果你想在指定的一个点开始你的笔迹,那么你可以使用 moveTo(x, y)
方法,如果你想从画笔的当前位置画线,可以使用 lineTo(x, y)
方法。
好了,下面就让我们开始画圆吧!实际上,还有一个 arc()
方法,可以让我们去画圆,不过在这之前,我们需要调用 beginPath()
方法。
function drawCircle(canvas, context) {
var radius = Math.floor(Math.random() * 48);
var x = Math.floor(Math.random() * canvas.width);
var y = Math.floor(Math.random() * canvas.height);
context.beginPath();
context.arc(x, y, radius, 0, Math.PI * 2, true);
context.fillStyle = "lightblue";
context.fill();
}
值得一提的是,arc()
方法中第四和第五个参数使用的都是弧度值,不过我们一般喜欢使用角度,比如 360 度,而不是 2 PI,所以我们可以写一个转换函数,然后你就可以尽情的使用熟悉的角度值了。
function degreesToRadians(degrees) {
return (degrees * Math.PI) / 180;
}
下面,你就可以画出下面这样的效果。
图形已经绘制完毕了,我们就去看看如何绘制文字,首先我们的获取输入控件中输入的文字,然后我们需要使用 context
的 measureText()
测量文字的宽度,因为我们想让文字居中。
function drawText(canvas, context) {
var selectObj = document.getElementById("foregroundColor");
var index = selectObj.selectedIndex;
var fgColor = selectObj[index].value;
var fontSize = "24";
context.fillStyle = fgColor;
context.font = "bold " + fontSize + "px sans-serif";
context.textAlign = "left";
var message = document.getElementById("message").value;
var messageWidth = context.measureText(message).width;
var x = Math.floor(canvas.width / 2 - messageWidth / 2);
var y = Math.floor(canvas.height / 2 - fontSize / 2);
context.fillText(message, x, y);
}
可以使用 context.font
设置文字相关的信息,第一个参数是 font style
, 可以设置为 bold
或者 italic
,第二个参数是文字的大小,第三个参数是 font family
,这里我指定为 sans-serif
。
你可能还有疑问的是,context.textAlign
是什么玩意?这个就是设置 fillText()
中 x 坐标指定的是文本哪个部位的坐标,如果你设置为 center
,那么这个 x
就是文本中间的 x 坐标。当然我们这里设置为 left
就是文本最左边的 x
坐标。
那么问题来了,我们为什么还要使用 measureText()
这么费劲的测试文本的宽度使文本居中呢?的确如此,我们可以使用 textAlign
轻易的实现文本居中,下面是对上述函数的改写。
function drawText(canvas, context) {
var selectObj = document.getElementById("foregroundColor");
var index = selectObj.selectedIndex;
var fgColor = selectObj[index].value;
var fontSize = "24";
context.fillStyle = fgColor;
context.font = "bold " + fontSize + "px sans-serif";
context.textAlign = "center"; // change
var x = Math.floor(canvas.width / 2); // change
var y = Math.floor(canvas.height / 2 - fontSize / 2);
var message = document.getElementById("message").value;
context.fillText(message, x, y);
}
文字也绘制完毕了,下面就绘制图形右下角的笑脸图片,当然这是个图片,不是一笔一笔画出来的。
function drawImage(canvas, context) {
var smileImage = new Image();
smileImage.src = "smile.png";
smileImage.onload = function() {
context.drawImage(smileImage, 632, 272, 24, 24);
}
}
drawImage()
的第二个参数是图形的左上角的 x 坐标,第三个参数是左上角的 y 坐标,第四个参数是图形的宽度,第五个参数是图形的高度。
这里为什么还是用一个 onload
呢?因为图片总是需要加载的,如果图片还没有加载完毕,就开始去绘制图片,肯定会绘制失败,所以我们利用一个回调,当图片加载完毕,再去绘制图片。
最后再来介绍一个目前浏览器支持不是很好的属性,我们可以将这个 Canvas
转化为一个图片,怎么样?听上去是不是很心动,其实写起来很容易。
function makeImage() {
var canvas = document.getElementById("myCanvas");
canvas.onclick = function() {
window.location = canvas.toDataURL("image/png");
}
}
这个时候,如果你的浏览器支持的话,只要你点击一些画布,那么就会有一个图片版本弹出来,供你保存到本地。
我在我的电脑上做了测试,只有 Firefox
支持这个功能,我喜欢的 Google Chrome, Opera, Yandex
在这方面的支持还不尽如人意。
如果你想要项目的源码,你可以到 我的 Github 下载源码。
Ending...