前言

本篇详细介绍canvas画布的API。说是详细介绍,也只是一些常用的API及简单实例和说明。LZ本人也还没有看完全部,下篇会介绍剩余的一些内容。

本篇的示例中,LZ加入了注释,为的是只简单介绍API确实挺无聊,也不那么容易理解,看代码看效果才最直接。

canvas APIs

canvas 基础api 介绍

在初始化Javascript函数中,用canvas标签的id获得canvas的DOM对象,并用getContext() 方法获得这个canvas的“2d”上下文对象,之后使用上下文对象调用canvas API 画图。

直线

画直线的功能可以用 beginPath(), moveTo(), lineTo() 和 stroke() 几个方法的组合来实现。

方法 beginPath() 定义了一个新的路径绘制动作的开始。

方法 moveTo() 为指定点创建了一个新的子路径,我们可以把

moveTo() 方法看成用来定位绘图鼠标用的(直线的起点,因为所有画线都和它相关,我们称之为上下文点)。

方法 lineTo() 从鼠标定位点,到方法参数中指定的点之间画一条直线。

方法 stroke() 为所画的线赋予颜色,并使其可见。如果没有特别的指定颜色的话,则默认使用黑色画直线。

上下文对象context的属性

context.lineWidth = 5; //设置宽度

context.strokeStyle = 'blue'; //设置颜色

context.lineCap = 'round'; //设置直线终点样式,可选值butt(默认值),round,和square。

示例如下

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>直线</title> <script>
window.onload = function () {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d"); // 最上面的线是butt样式
context.beginPath();
context.moveTo(200, canvas.height / 2 - 50);
context.lineTo(canvas.width - 200, canvas.height / 2 - 50);
context.lineWidth = 10;
context.strokeStyle = "#ff0000";
context.lineCap = "butt";
context.stroke(); // 中间的线是round样式
context.beginPath();
context.moveTo(200, canvas.height / 2);
context.lineTo(canvas.width - 200, canvas.height / 2);
context.lineWidth = 15;
context.strokeStyle = "#00ff00";
context.lineCap = "round";
context.stroke(); // 最下面的是square样式
context.beginPath();
context.moveTo(200, canvas.height / 2 + 50);
context.lineTo(canvas.width - 200, canvas.height / 2 + 50);
context.lineWidth = 20;
context.strokeStyle = "#0000ff";
context.lineCap = "square";
context.stroke();
}; </script>
</head>
<body>
<canvas id="myCanvas" width="578" height="200"></canvas>
</body>
</html>

效果如图:

弧线

画弧线的方法是 arc()。每条弧线都需要由中心点、半径、起始角度(弧度n*Math.PI)、结束角度(弧度m*Math.PI)和绘图方向(顺时针 false 还是逆时针true)这几个参数来确定。如context.arc(x, y, radius, startAngle, endAngle, antiClockwise);

二次曲线

二次曲线使用quadraticCurveTo()方法来绘制。每条二次曲线要由上下文点、一个控制点和一个终止点来定义。

context.quadraticCurveTo(controlX, controlY, endX, endY);

贝塞尔曲线

绘制贝塞尔曲线使用方法bezierCurveTo() 。每条贝塞尔曲线需要由上下文点、两个控制点和一个终止点来确定。如:

context.bezierCurveTo(controlX1, controlY1, controlX2, controlY2, endX, endY);

圆角

画圆角使用方法 arcTo() 。此方法需要一个控制点、一个终止点和半径作为必要的参数。如:

context.arcTo(controlX,controlY,endX,endY,radius);

画路径

路径是由多条子路径连接构成的。每条子路径的终止点就将作为新的上下文点。我们可以使用lineTo(), arcTo(), quadraticCurveTo() 和 bezierCurveTo() 创建新的子路径。每次要开始画一条路径的时候就要使用 beginPath() 方法。

canvas支持3种线条的连接样式,包括: miter, round, 和 bevel。 设定连接样式是用 lineJoin 属性设定。缺省情况下,将使用 miter 样式。

上边几个的代码示例如下:

 <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script>
window.onload = function () {
ords();
arc();
//quadratic();
//bezier();
//arcTo();
//path();
};
//弧线
function arc() {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var x = canvas.width / 2, y = canvas.height / 2;//圆心坐标
var radius = 75; //半径
var startAngle = 0.5 * Math.PI, //开始弧度
endAngle = 2 * Math.PI, //结束弧度
counterClockwise = false; //画图方向,false-顺时针,true-逆时针,注意对绘画效果的影响!!
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
//context.lineWidth = 15;
//context.strokeStyle = "black";
//context.stroke();
context.fillStyle = "blue";
context.fill();
}
//二次曲线
function quadratic() {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d"); context.beginPath();
context.moveTo(188, 150);//起始点
context.quadraticCurveTo(328, 50, 388, 150);//控制点和结束点
context.lineWidth = 10;
context.strokeStyle = "black";
context.stroke();
}
//贝赛尔曲线
function bezier() {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.beginPath();
context.moveTo(188, 130);
context.bezierCurveTo(80, 10, 188, 10, 388, 170);//控制点1,控制点2和结束点
context.lineWidth = 10;
context.strokeStyle = "black";
context.stroke();
}
//圆角
function arcTo() {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var rectWidth = 200,//矩形框宽度
rectHeight = 100,//高度
rectX = 189,//起点
rectY = 50,
cornerRadius = 50;//圆角半径
context.beginPath();
context.moveTo(rectX, rectY);
context.lineTo(rectX + rectWidth - cornerRadius, rectY);//直线坐标点,x坐标减去圆角半径
context.arcTo(rectX + rectWidth, rectY, rectX + rectWidth, rectY + cornerRadius, cornerRadius);//圆角起始点坐标和半径
context.lineTo(rectX + rectWidth, rectY + rectHeight);//此时起点y坐标是圆角结束点rectY + cornerRadius
context.lineWidth = 5;
context.stroke();
}
//路径
function path() {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d"); context.beginPath();
context.lineJoin = "round";//线间链接样式:可选值miter(默认), round, 和 bevel。
context.moveTo(100, 20);
context.lineTo(220, 60);
// 第一条直线
context.lineTo(200, 160);
// 二次曲线
context.quadraticCurveTo(230, 200, 250, 120);
// 贝塞尔曲线
context.bezierCurveTo(290, -40, 300, 200, 400, 150);
// 第二条直线
context.lineTo(500, 90);
context.lineWidth = 15;
context.strokeStyle = "blue";
context.closePath();
context.stroke(); }
//坐标系
function ords() {
for (var i = 0; i < 50; i++) {
drawDirectedLine(i * 20, 0, false);//纵向,只关心横坐标
drawDirectedLine(0, i * 20, true);//横向,只关心纵坐标
}
}
//起点坐标,直线方向:true-横向,false-纵向
function drawDirectedLine(x1, y1, d) {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.beginPath();
context.strokeStyle = "#ff3333";
if (d) {
context.moveTo(0, y1);
context.lineTo(1000, y1);
}
else {
context.moveTo(x1, 0);
context.lineTo(x1, 1000);
}
context.stroke();
}
</script>
</head>
<body>
<canvas id="myCanvas" width="578" height="250"></canvas>
</body>
</html>

线性渐变

要使用线性渐变效果填充图形,首先要使用 createLinearGradient() 方法从上下文对象中创建线性渐变对象。

createLinearGradient() 方法的四个参数确定一条虚拟线段,渐变就沿着此条线段的方向。

然后用 addColorStop 方法为线性渐变对象设置渐变线上的关键点的颜色,offset 表示关键点是在渐变虚拟线段的什么位置, offset 的取值范围是0到1,其中0表示是起始点,1表示是终止点,0到1之间的值表示是此虚拟线段中间的某一位置。

再将此线性渐变对象作为填充类型赋值给上下文对象的 fillStyle 属性。canvas将根据渐变虚拟线段上关键点的颜色变化填充图形。

示例代码:

  function linear() {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d"); var grd = context.createLinearGradient(0, 0, 450, 400);//渐变路径从(0,0) 到(450,300) grd.addColorStop(0, "#000000");
grd.addColorStop(0.5, "#ff0000");
grd.addColorStop(1, "#ffffff"); ////查看渐变效果。
//context.beginPath();
//context.fillStyle = grd;
//context.fillRect(0, 0, 450, 400); context.beginPath();
context.moveTo(170, 80);//起点
context.bezierCurveTo(130, 100, 130, 150, 230, 150);//两个控制点,一个终结点(下一个路径的起点)
context.bezierCurveTo(250, 180, 320, 180, 340, 150);
context.bezierCurveTo(420, 150, 420, 120, 390, 100);
context.bezierCurveTo(430, 40, 370, 30, 340, 50);
context.bezierCurveTo(320, 5, 250, 20, 250, 50);
context.bezierCurveTo(200, 5, 150, 20, 170, 80);
context.closePath(); //圆周
context.strokeStyle = "blue";
context.lineWidth = 15;
context.closePath();
context.stroke();
//填充
context.fillStyle = grd;
context.fill(); }

效果如图:

      

径向渐变

径向渐变与线性渐变类似,只不过渐变方向不是线段,而是两个圆之间。使用 createRadialGradient() 方法创建渐变对象,参数是渐变起始圆和终止圆。如:

context.createRadialGradient(startX, startY, startRadius, endX, endY, endRadius);

示例代码:

  function Radial() {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.beginPath(); //三处注释效果不一样,可对比查看
//注释一 示例作图
context.moveTo(170, 80);
context.bezierCurveTo(130, 100, 130, 150, 230, 150);//两个控制点,一个终结点
context.bezierCurveTo(250, 180, 320, 180, 340, 150);
context.bezierCurveTo(420, 150, 420, 120, 390, 100);
context.bezierCurveTo(430, 40, 370, 30, 340, 50);
context.bezierCurveTo(320, 5, 250, 20, 250, 50);
context.bezierCurveTo(200, 5, 150, 20, 170, 80);
context.closePath();
// 创建径向渐变对象
var grd = context.createRadialGradient(238, 50, 10, 238, 50, 200);//两个圆心+半径
// 设置渐变起始圆处的颜色
grd.addColorStop(0, "#FF0000");
// 设置渐变终止圆处的颜色
grd.addColorStop(1, "#00FF00"); ////注释二 查看渐变效果
//context.arc(238, 50, 10, 0, Math.PI * 2, true);
////同心圆效果
////context.arc(238, 50, 200, 0, Math.PI * 2, true);
////非同心圆效果
//context.arc(238, 200, 200, 0, Math.PI * 2, true); ////注释三 拉开距离 查看两个圆的效果
//context.arc(800, 50, 10, 0, Math.PI * 2, true);
//context.arc(800, 400, 200, 0, Math.PI * 2, true); context.strokeStyle = "blue";
context.lineWidth = 2;
context.closePath();
context.stroke();
context.fillStyle = grd;
context.fill();
}

效果如图:

       

绘制图像

绘制图像需要使用 drawImage() 方法。此方法需要一个图像对象和一个起始点坐标作为参数,其中起始点坐标是相对于canvas的左上角的位置。如:

context.drawImage(imageObj, x, y);

由于 drawImage() 方法需要一个图像对象作为参数,所以我们需要在实际调用 drawImage() 之前就加载图像。这一要求可以通过图像对象的 onload 事件来实现。不过要注意的是, onload 应该在用图像对象的src属性指定图像来源之前就进行赋值。

方法 drawImage() 还可以接受 destWidth 和 destHeight 两个参数用来以任意指定的尺寸显示图像:

context.drawImage(imageObj, x, y, width, height);

方法 drawImage() 还可以增加另六个参数来实现对图像的裁剪。这六个参数是, sourceX,sourceY, sourceWidth, sourceHeight, destWidth 和 destHeight。这六个参数对应的含义可以参阅示意图。  context.drawImage(imageObj, sx, sy, sw, sh, dx, dy, dw, dh);

图片来源(https://developer.mozilla.org/zh-CN/docs/Web/Guide/HTML/Canvas_tutorial/Using_images#Using_images_which_are_on_the_same_page)

示例代码:

 function drawImg() {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var img = new Image();
//为保证图片加载,在其load方法中添加绘图方法
img.onload = function () {
context.drawImage(img, 0, 200);//原图输出在位置(0,300)
context.drawImage(img, 0, 0, 100, 100);//在位置(0,0)将图画成(缩放) 100*100
context.drawImage(img, 50, 50, 150, 150, 0, 120, 100, 130);//将原图从左上角(50,50)到右下角(150,150)裁剪下来,在位置(0,120)缩放成100*130的图片 var pattern = context.createPattern(img, "repeat");
context.fillStyle = pattern;
context.fillRect(0, 400, canvas.width - 20, canvas.height - 20);//填充一个矩形
}
img.src = "http://w3school.com.cn/i/ct_html5_canvas_image.gif";
}

效果图如下:

文本的字体、大小和样式

友情提醒:这里介绍文字略多,可先运行示例,查看效果再回头看介绍,那样就一目了然了。

要设置字体、大小和样式,需要用到上下文对象的 font 属性。样式可以是 normal, italic 或 bold 。默认情况是 normal 。

context.font = 'italic 40px Calibri';

文本的颜色用 fillStyle 属性设置

要描绘字体边缘的效果,要使用 strokeText() 方法替代fillText(),同时要用strokeStyle 属性替代 fillStyle 属性。

文本的对齐功能设定使用 textAlign 属性。其可用的选项包括 start, end, left, center和 right 。对齐的位置是相对于一条虚拟的垂直线,这条线是由 fillText() 或 strokeText() 定义的文本x位置。

垂直对齐文本需要用到 textBaseline 属性。此属性可用的选项包括:top, hanging,middle, alphabetic, ideographic 和 bottom 。默认情况下是alphabetic 。

要获取有关文本的尺度信息,可以使用 measureText() 方法。此方法需要一个文本字符串组为参数,并返回一个尺度对象。尺度对象中的数据是基于所提供的字符串参数和当前的文本字体信息而来的。注意:由于文本的像素高度等于字体尺寸的磅值,所以,从 measureText() 返回的尺度对象并不包含高度数据。如:

var metrics = context.measureText("text");

var width = metrics.width;

示例代码如下:

 <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script> window.onload = function () {
font();
wrapText();
}; function font() {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); // 在位置 300 创建蓝线
ctx.strokeStyle = "blue";
ctx.moveTo(300, 20);
ctx.lineTo(300, 200);
ctx.stroke(); ctx.font = "15px Arial"; // 显示不同的 textAlign 值
ctx.textAlign = "start";
ctx.fillText("textAlign=start", 300, 60);
ctx.textAlign = "end";
ctx.fillText("textAlign=end", 300, 80);
ctx.textAlign = "left";
ctx.fillText("textAlign=left", 300, 100);
ctx.textAlign = "right";
ctx.fillText("textAlign=right", 300, 140);
ctx.textAlign = "center";
ctx.fillText("textAlign=center", 300, 120); //在位置 y=300 绘制蓝色线条
ctx.strokeStyle = "blue";
ctx.moveTo(5, 300);
ctx.lineTo(395, 300);
ctx.stroke(); ctx.font = "20px Arial" //在 y=300 以不同的 textBaseline 值放置每个单词
ctx.textBaseline = "top";
ctx.fillText("Top", 25, 300);
ctx.textBaseline = "bottom";
ctx.fillText("Bottom", 50, 300);
ctx.textBaseline = "middle";
ctx.fillText("Middle", 120, 300);
ctx.textBaseline = "alphabetic";
ctx.fillText("Alphabetic", 200, 300);
ctx.textBaseline = "hanging";
ctx.fillText("Hanging", 290, 300); } function wrapText() { var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var maxWidth = 300;
var lineHeight = 25;
var x = (canvas.width - maxWidth) / 2;
var y = 400;
var text = "All the world 's a stage, and all the men and women merely players. They have their exits and their entrances; And one man in his time plays many parts.";
context.font = "16pt Calibri";
//context.fillStyle = "#333"; // 创建渐变
var gradient = context.createLinearGradient(0, 0, canvas.width, 0);
gradient.addColorStop("0", "magenta");
gradient.addColorStop("0.5", "blue");
gradient.addColorStop("1.0", "red");
// 用渐变填色
context.fillStyle = gradient;
context.textBaseline = 'bottom'; var words = text.split(" ");
var line = "";
for (var n = 0; n < words.length; n++) {
var testLine = line + words[n] + " ";
var metrics = context.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth) {//大于最大长度 则将当前行输出,然后换行(y增加)并将换行后的首字母赋值给line
context.fillText(line, x, y);
line = words[n] + " ";
y += lineHeight;
} else {
line = testLine;
}
}
context.fillText(line, x, y);//最后一行
}
</script>
</head>
<body>
<canvas id="myCanvas" width="1000" height="600"></canvas>
</body>
</html>

效果如图(由于LZ截图问题,设置的居中在图中是不居中的):

小结

本篇介绍了线、路径、渐变和文本,下篇将介绍阴影、状态储存和恢复等。

由于LZ现在不如之前清闲了,可能会耽误进度,但是我会尽量坚持写完该系列,谢谢支持。

HTML5简单入门系列(七)的更多相关文章

  1. HTML5简单入门系列(五)

    前言 本篇将讲述HTML5的服务器发送事件(server-sent event) Server-Sent 事件 Server-Sent 事件是单向消息传递,指的是网页自动获取来自服务器的更新. 以前的 ...

  2. HTML5简单入门系列(六)

    前言 之前几篇已经将HTML5的主要新增元素和特性简单介绍完毕,LZ一直在犹豫还要不要把其他元素也写出来,因为其实没什么东西可以写,就是自己用到时看一下就行.不过为了入门系列的完整,犹豫再三,还是决定 ...

  3. HTML5简单入门系列(九)

    前言 上篇本来应该就是最后一篇了,但是楼主总觉得没有写上一个简单应用,不算是完整的学习系列.所以增加一篇关于动画的应用,对一个开源动画的介绍(很基础,非楼主原创). 本篇介绍一个基于Canvas的发光 ...

  4. HTML5简单入门系列(八)

    前言 本篇介绍HTML5中相对复杂的一些APIs,其中的数学知识比较多.虽然如此,但是其实API使用起来还是比较方便的. 这里说明一下,只写出API相关的JS代码,因为他们都是基于一个canvas标签 ...

  5. HTML5简单入门系列(一)

    前言 随着HTML5的流行,LZ作为一个web开发者,也决定学习一下前端前沿技术. HTML5 是下一代的HTML,它将成为 HTML.XHTML 以及 HTML DOM 的新标准.它是W3C( Wo ...

  6. HTML5简单入门系列(四)

    前言 今天这篇内容主要讲述HTML 5 Web Worker(一种支持前端js多线程的技术). 工作线程(Web Worker) web worker介绍 W3C 在 HTML5 的规范中提出了工作线 ...

  7. HTML5简单入门系列(三)

    前言 本篇介绍HTML5支持的Web存储(Web Storage)和HTML 5 应用程序缓存. 客户端存储数据介绍 HTML5 提供了两种在客户端存储数据的新方法: localStorage - 没 ...

  8. HTML5简单入门系列(二)

    前言 上篇中写到HTML5中的画布(canvas)元素,查看了canvas其他的资料,发现这个元素相关内容太多,鉴于本系列只是基础(主要是LZ也是初学),不再做太多介绍,有机会的话再单独写相关内容.说 ...

  9. 07. Web大前端时代之:HTML5+CSS3入门系列~H5 地理位置

    Web大前端时代之:HTML5+CSS3入门系列:http://www.cnblogs.com/dunitian/p/5121725.html 源码:https://github.com/duniti ...

随机推荐

  1. win32下用VC扩展PHP全过程

    闲着无聊,打算开发一些PHP组件来玩玩,由于在家没有工作环境,遂打算在win32(我的环境是vista)用VC开发DLL模块,费话不 多说了,进入正题: 一.已经在机器上安装PHP环境的就略过,否则先 ...

  2. ecstore后台规格超过一定数量保存丢失

    问题描述: 后台规格超过一定数量保存丢失,规格新增不了,删除出问题等不正常情况. 解决方法: 经过波波的不懈努力和日夜冥想终于破了.分析其原因就是因为多个规格组合生成的表单域太多,与php.ini配置 ...

  3. Identify Smith Numbers

    Link: https://www.hackerrank.com/challenges/identify-smith-numbers def sum_digits(n): return sum(int ...

  4. hdu 5363Key Set

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5363 Problem Description soda has a set S with n inte ...

  5. IOS APP配置.plist汇总(转自coolweather )

    IOS APP配置.plist汇总(转自coolweather ) 此文转自http://www.cocoachina.com/bbs/read.php?tid=89684&page=1 作者 ...

  6. [POJ] 3461 Oulipo [KMP算法]

    Oulipo Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 23667   Accepted: 9492 Descripti ...

  7. 去除winXP访问共享的“记住密码”

    控制面板->用户帐户,选择自己的用户,在左侧的管理我的网络密码里有删除选项 控制面板-->用户-->点击你登陆用户-->点击左上角“管理我的网络密码”-->在列表中删除密 ...

  8. 如何删除textarea的移动版Safari的阴影?

    如何删除textarea的移动版Safari的阴影? 在iphone的Safari上运行网页,textarea无法使用box-shadow样式,而且顶部有内阴影,如何清除? 添加评论 分享   赞同1 ...

  9. Codeforces 414B Mashmokh and ACM

    http://codeforces.com/problemset/problem/414/B 题目大意: 题意:一个序列B1,B2...Bl如果是好的,必须满足Bi | Bi + 1(a | b 代表 ...

  10. The Angles of a Triangle

    The Angles of a Triangle You are given the lengths for each side on a triangle. You need to find all ...