HTML5与移动Web开发:Canvas画布

1,Canvas标签

1.1,canvas简介

<canvas> 是 HTML5 新增的,一个可以使用脚本(通常为JavaScript)在其中绘制图像的 HTML 元素。它可以用来制作照片集或者制作简单(也不是那么简单)的动画,甚至可以进行实时视频处理和渲染。Canvas是由HTML代码配合高度和宽度属性而定义出的可绘制区域。JavaScript代码可以访问该区域,类似于其他通用的二维API,通过一套完整的绘图函数来动态生成图形。Mozilla 程序从 Gecko 1.8 (Firefox 1.5)开始支持 <canvas>, Internet Explorer 从IE9开始<canvas> 。Chrome和Opera 9+ 也支持 <canvas>。它最初由苹果内部使用自己MacOS X WebKit推出,供应用程序使用像仪表盘的构件和 Safari 浏览器使用。 后来,有人通过Gecko内核的浏览器 (尤其是Mozilla和Firefox),Opera和Chrome和超文本网络应用技术工作组建议为下一代的网络技术使用该元素。浏览器支持:Chrome 4.0+IE 9.0+FireFox 2.0+Safari 3.1+Opera9.0+

<canvas>标签是html5出现的新标签,像所有的dom对象一样它有自己本身的属性、方法和事件,其中就有绘图的方法。<canvas>标签是为了客户端矢量图形而设计的。它自己没有行为,但却把一个绘图API展现给客户端JavaScript,以使脚本能够把想绘制的东西都绘制到一块画布上。

canvas画布是一个矩形区域,您可以控制其每一像素。同时,canvas也拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。

1.2,Canvas标签

在向HTML5页面中添加Canvas元素时,需要设置元素的id、宽度和高度,例如:

<canvas id="tutorial" width="300" height="300">您的浏览器不支持canvas标签</canvas>
  • Canvas本质上一个位图画布,其上绘制的图形是不可缩放的,不能像SVG图像那样可以被放大缩小。
  • 用Canvas绘制出来的对象不属于页面DOM结构或者任何命名空间。
  • <canvas>由于不存储文档对象,性能较好,但如果需要移除画布中的图形元素,往往需要擦掉绘图重新绘制它。
  • <canvas>看起来和<img>标签一样,只是 <canvas> 只有两个可选的属性 width、heigth 属性,而没有 src、alt 属性。另外<canvas>元素需要结束标签(</canvas>)。如果结束标签不存在,则文档的其余部分会被认为是替代内容,将不会显示出来。
  • ​ 如果不给<canvas>设置widht、height属性时,则默认 width为300、height为150,单位都是px。也可以使用css属性来设置宽高,但是如宽高属性和初始比例不一致,他会出现扭曲。所以,建议永远不要使用css属性来设置<canvas>的宽高。

由于某些较老的浏览器(尤其是IE9之前的IE浏览器)或者浏览器不支持HTML元素<canvas>,在这些浏览器上你应该总是能展示替代内容。 支持<canvas>的浏览器会只渲染<canvas>标签,而忽略其中的替代内容。不支持 <canvas> 的浏览器则 会直接渲染替代内容。

1.用文本替换:
<canvas>
    你的浏览器不支持canvas,请升级你的浏览器
</canvas>
2.用 <img> 替换:
<canvas>
    <img src="./美女.jpg" alt=""> 
</canvas>

1.3,绘图流程

(1)获取canvas对象

var canvas=document.getElementById("canvas1");

(2)检查是否支持

var canvas = document.getElementById('tutorial');
if (canvas.getContext){
  var ctx = canvas.getContext('2d');
  // drawing code here
} else {
  // canvas-unsupported code here
}

(3)获取画布对象:canvas对象包含了不同类型的绘图API,还需要使用getContext()方法来获取接下来要使用的绘图上下文对象

var context=canvas.getContext("2d");
//参数2d,说明将要绘制的是一个二维图形

(4)在Canvas上绘制文字

//设置字体样式、颜色及对齐方式
context.font="98px 黑体";
context.fillStyle="#026";
context.textAlign="center";
//绘制文字
context.fillText("中",100,120,200);

2,绘制基本图形 

2.1,绘制矩形

<canvas> 只支持一种原生的图形绘制:矩形所有其他图形都至少需要生成一种路径(path)。不过,我们拥有众多路径生成的方法让复杂图形的绘制成为了可能。

  • fillRect(x, y, width, height):绘制一个填充的矩形
  • strockRect(x, y, width, height):绘制一个矩形的边框
  • clearRect(x, y, widh, height):清除指定的矩形区域,然后这块区域会变的完全透明。
<html>
	<body>
		<canvas id="canvas1" width="400" height="400">
			如果浏览器不支持canvas标签,可以用改文字或者下面图片替代
			<img src="***"/>
		</canvas>
		<script type="text/javascript">
			var myCanvas = document.getElementById("canvas1");
			var con1 = myCanvas.getContext("2d");
			//绘制矩形边框
			con1.strokeStyle = "red"; //设置边框颜色
			con1.lineWidth = 10; //设置边框宽度
			con1.strokeRect(50, 50, 300, 300); //绘制矩形边框 
			//填充矩形区域
			con1.fillStyle = "rgba(6,191,247,0.8)"; //设置填充颜色
			con1.fillRect(70, 70, 360, 360); //填充矩形区域
			con1.clearRect(65, 65, 50, 215);	//清除一个矩形的图像
		</script>
	</body>
</html>

2.2,绘制路径

图形的基本元素是路径。路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。一个路径,甚至一个子路径,都是闭合的。

使用路径绘制图形需要一些额外的步骤:

  • 创建路径起始点。
  • 调用绘制方法去绘制出路径。
  • 把路径封闭。
  • 一旦路径生成,通过描边或填充路径区域来渲染图形。

下面是需要用到的方法:

  • beginPath()新建一条路径,路径一旦创建成功,图形绘制命令被指向到路径上生成路径。
  • moveTo(x, y):把画笔移动到指定的坐标(x, y)。相当于设置路径的起始点坐标。
  • closePath()闭合路径之后,图形绘制命令又重新指向到上下文中。
  • stroke()通过线条来绘制图形轮廓。
  • fill()通过填充路径的内容区域生成实心的图形

2.3,绘制线段

Canvas上画线,将使用以下两种方法:

  • moveTo(x, y):不绘制,只是将当前位置移动到新的目标坐标(xy
  • lineTo(x, y) :不仅将当前位置移动到新的目标坐标(xy),而且在两个坐标之间画一条直线。

moveTo就像是提起画笔,移动到新位置,而lineTo告诉canvas用画笔从纸上的旧坐标画条直线到新坐标。

  • 特殊函数closePath:这个函数的行为和lineTo很像,唯一的差别在于closePath会将路径的起始坐标自动作为目标坐标。closePath还会通知canvas当前绘制的图形已经闭合或者形成了完全封闭的区域,这对将来的填充和描边都非常有用。

注意:不管调用它们哪一个,都不会真正画出图形,因为我们还没有调用stroke或者fill函数。目前,我们只是在定义路径的位置,以便后面绘制时使用。

<html>
    <body>
		<canvas id="canvas1" width="600" height="250" style="border: 1px solid red;">
			你的浏览器不支持该功能
		</canvas>
		<script type="text/javascript">
			var myCanvas = document.getElementById("canvas1");
			var con1 = myCanvas.getContext("2d");
			//绘制第一条直线
			con1.moveTo(20, 20);
			con1.lineTo(400, 150); //绘制一条从当前位置到指定坐标(400, 150)的直线.
			con1.lineTo(20, 150);
			con1.closePath()
			con1.lineWidth = 15;
			con1.strokeStyle = "cyan";
			con1.stroke();
			
			con1.fillStyle="yellow"
			con1.fill()
			
			con1.stroke();
		</script>
		</body>
</html>

2.4,绘制圆弧

要想绘制其他图形,需要使用路径。同绘制矩形一样,绘制开始时还是要取得图形上下文,然后需要执行如下步骤:

(1)开始创建路径:使用图形上下文对象的beginPath()方法,该方法不使用参数,通过调用该方法,开始路径的创建。

context.beginPath()

(2)创建图像的路径:使用图形上下文对象的arc()方法。

context.arc(x,y,radius, startAngle, endAngle, anticlockwise)
    x为绘制圆形的起点横坐标
    y为绘制圆形的起点纵坐标
    radius为圆形半径
    startAngle为开始角度
    endAngle为结束角度
    anticlockwise为是否按顺时针方向进行绘制。

arcTo(x1, y1, x2, y2, radius)
    参数1、2:控制点1坐标   
    参数3、4:控制点2坐标  
    参数5:圆弧半径

根据给定的控制点和半径画一段圆弧,最后再以直线连接两个控制点。 绘制的弧形是由两条切线所决定(其实绘制的圆弧就是与这两条直线相切的圆弧):

  • 起点与第一个控制点连接成一条直线。
  • 第一个控制点与第二个控制点连接成一条直线。
  • 那么通过这两条直线与圆的半径可以绘制一个与直线相切的圆弧。
  • 起点与圆弧连接起来,就是最终绘制的图案。
<html>
	<body>
		<canvas id="canvas1" width="500" height="500">
			你的浏览器不支持该功能
		</canvas>
		<script type="text/javascript">
			var myCanvas = document.getElementById("canvas1");
			var con1 = myCanvas.getContext("2d");
			//先绘制一个圆形
			con1.beginPath();
			con1.arc(250, 250, 230, 0, Math.PI * 2, true);
			con1.closePath();
			con1.fillStyle = "rgba(255,0,0,0.4)";
			con1.fill();
			//再绘制一条圆弧
			con1.beginPath();
			con1.arc(250, 250, 240, 0, (-Math.PI * 1), true);
			con1.strokeStyle = "cyan";
			con1.lineWidth = 20;
			con1.stroke();
		</script>
	</body>
</html>

2.5,绘制贝塞尔曲线

贝塞尔曲线,又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的。绘制贝塞尔曲线主要使用bezierCurveTo方法。该方法可以说是lineTo的曲线版,将从当前坐标点到指定坐标点中间的贝塞尔曲线追加到路径中。

bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

绘制贝塞尔曲线的时候,需要两个控制点:
    cp1x为第一个控制点的横坐标
    cp1y为第一个控制点的纵坐标
    cp2x为第二个控制点的横坐标
    cp2y为第二个控制点的纵坐标
    x为贝塞尔曲线的终点横坐标
    y为贝塞尔曲线的终点纵坐标

【线性贝塞尔曲线】实际上就是一条直线。

【二阶贝塞尔曲线】绘制二次样条曲线,使用的方法是quadraticCurveTo

bezierCurveTo(cp1x, cp1y, x, y)

x 和 y 是终点坐标
cp1x 和 cp1y 是第一个控制点的坐标

【三阶贝塞尔曲线】

bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

【二次贝塞尔曲线】绘制二次样条曲线,使用的方法是quadraticCurveTo

quadraticCurveTo(cp1x, cp1y, x, y)

特别说明:黑色曲线是真正绘制出的贝塞尔曲线,黄色是辅助线。开始点与控制点连接成一条线段,控制点又和结束点连接成一条线段;二次贝塞尔曲线两端和两条线段相切,通过移动控制点的坐标可以绘制出不同的曲线。

quadraticCurveTo和bezierCurveTo的区别:它们都是一个起点一个终点(图中的蓝点),但二次方贝塞尔曲线只有一个(红色)控制点点)而三次方贝塞尔曲线有两个。参数 x y 是终点坐标,cp1x cp1y 是第一个控制点的坐标,cp2x cp2y 是第二个的。

3,填充及其他样式

3.1,填充颜色

如果想要给图形上色,有两个重要的属性可以做到:fillStyle 和 strokeStyle。这两个属性的定义方法如下所示:

  • fillStyle = color
  • strokeStyle = color

strokeStyle 是用于设置图形轮廓的颜色,而 fillStyle用于设置填充颜色。color 可以是表示 CSS 颜色值的字符串、渐变对象或者图案对象。默认情况下,线条和填充颜色都是黑色(CSS 颜色值 #000000)。

3.2,透明度

通过设置 globalAlpha属性或者使用一个半透明颜色作为轮廓或填充的样式来绘制透明或半透明的图形(透明度属性只会对后面的路径或者子路径生效)。

globalAlpha = transparency value

这个属性影响到 canvas 里所有图形的透明度,其有效的值范围是 0.0 (完全透明)到 1.0(完全不透明),默认是 1.0。

3.3,图形叠加

这个用起来就类似CSS的 Z-index 感觉有点像,可以设置哪个图形显示的位置居上或居下,也可以更加的细分的画出叠加到一起时的各种样式:

ctx.globalCompositeOperation="属性值"
    source-over :默认。在目标图像上显示源图像。
    source-atop : 在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。
    source-in : 在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。
    source-out : 在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。
    destination-over : 在源图像上方显示目标图像。
    destination-atop : 在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示。
    destination-in : 在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。
    destination-out : 在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。
    lighter : 显示源图像 + 目标图像。
    copy : 显示源图像。忽略目标图像。
    xor : 使用异或操作对源图像与目标图像进行组合。

3.4,线型

lineWidth 属性:该属性设置当前绘线的粗细,属性值必须为正数。默认值是1.0。线宽是指给定路径的中心到两边的粗细。换句话说就是在路径的两边各绘制线宽的一半。同时画布的坐标并不和像素直接对应,当需要精确的水平或者垂直线的时候需要注意。

lineCap 属性:该属性决定了线段端点显示的样子。它可以为下面的三种值之一:buttround square,默认是 butt

  • round就是在起终点都加上一个直径为线宽的半圆。
  • square就是在起终点加上一个高度为线宽一半的方块。

使用round属性值会比默认值butt多出一个半圆的形状包在线段的开始和结尾处,而是用square属性值会在开始和结尾处多处半个方形,这就是它们的不同之处。其中,round对于我们绘制一些圆角效果的图形比较有用,但是它只对线条的开头和结尾处有效果,对于线段之间的连接处没有作用,这点需要注意。

lineJoin 属性:该属性值决定了图形中两线段连接处所显示的样子。它可以是以下三种值之一:round(圆角), bevel(衔接) 和 miter(默认值,尖角)。

miterLimit属性:设置或返回最大斜接长度。这个属性只有当lineJoin属性值是miter时才有用,默认值是10。

斜接长度指的是在两条线交汇处内角和外角之间的距离:边角的角度越小,斜接长度就会越大。

为了避免斜接长度过长,我们可以使用 miterLimit 属性。 如果斜接长度超过 miterLimit 的值,边角会以 lineJoin 的 "bevel" 类型来显示

如果将五角星的角设置的很小,就变成了bevel的情况:

3.5,文本

画布中不仅可以绘制图形,还可以绘制文本。绘制文本,既可以使用填充方法,也可以使用勾勒方法:

fillText(text, x, y, [maxWidth])
strokeText(text, x, y, [maxWidth])
    表示在(x,y)的位置,绘制text的内容。
    可选参数maxWidth为文本的最大宽度,单位为像素。如果设置了该属性,当文本内容宽度超过该参数值,则会自动按比例缩小字体,使文本的内容全部可见;未超过时,则以实际宽度显示。如果未设置该属性,当文本内容宽度超过画布宽度时,超出的内容将被隐藏。
<!DOCTYPE html>
<html>
	<body>
		<canvas id="canvas1" width="600" height="250" style="border: 1px solid red;">
			你的浏览器不支持该功能
		</canvas>
		<script type="text/javascript">
			var myCanvas = document.getElementById("canvas1");
			var con1 = myCanvas.getContext("2d");
			//绘制第一条直线
			con1.font = "20px Georgia";
			con1.fillText("Hello World!", 10, 50);
			con1.strokeText("Hello Java", 10, 70)
		</script>
	</body>
</html>

为保证文本在各浏览器下显示一致,需要设置文本的样式属性,可设置的属性见表:

  • textAlign属性定义的是x坐标点的位置,假设其值为"center",则x坐标点就在文本的中心点的位置,其值为"left",则x坐标点就在文本的最左边的位置。
  • 对于从左到右的文本而言,"start""left"是等价的,"end""right"是等价的;
  • 对于从右到左的文本而言,"start""right "是等价的,"end""left "是等价的。
  • 可以通过<canvas>元素的dir属性来设置文本的方向,“rtl”(right-to-left)表示从右到左,“ltr”( left-to-right)表示从左到右。

获取文字宽度:有时我们需要知道所绘制的文本宽度,以方便进行布局。绘图API提供了获取绘制文本宽度的方法,measureText(text);参数text表示所要绘制的文本,该方法返回一个TextMetrics对象,表示文本空间度量,可以通过该对象的width属性获取文本的宽度。

4,渐变

渐变是一种很普遍的视觉效果,能带来视觉上的舒适感。在canvas中,绘图API提供了两个原生的渐变方法,包括线性渐变和径向渐变。使用渐变需要3个步骤:首先是创建渐变对象;其次是设置渐变颜色和过渡方式;最后将渐变对象赋值给填充样式或描边样式。使用渐变对象,必须使用两种或两种以上的停止颜色。

4.1,线性渐变

线形渐变指的是一条直线上发生的渐变,绘制线性渐变时,需要使用到LinearGradient对象。使用图像上下文对象的createLinearGradient()方法创建该对象:

context.createLinearGradient(xStart,yStart,xEnd,yEnd)
    xStart为渐变起始地点的横坐标
    yStart为渐变起始地点的纵坐标
    xEnd为渐变结束地点的横坐标
    yEnd为渐变结束地点的纵坐标

设置渐变颜色需要在渐变对象上使用addColorStop()方法,在渐变中的某一点添加一个颜色变化:

addColorStop(offset,color)
    offset为所设定的颜色离开渐变起始点的偏移量。该参数的值是一个范围在0到1之间的浮点值,渐变起始点的偏移量为0,渐变结束点的偏移量为1。 
水平渐变:var grd = con1.createLinearGradient(0, 0, 0, 400);
垂直渐变:var grd = con1.createLinearGradient(0, 0, 400, 0);
对角渐变:var grd = con1.createLinearGradient(0, 0, 400, 900);
<html>
	<body>
		<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
			Your browser does not support the HTML5 canvas tag.
		</canvas>
		<script>
			var c = document.getElementById("myCanvas");
			var ctx = c.getContext("2d");

			var grd = ctx.createLinearGradient(0, 0, 170, 0);	//设置渐变
			grd.addColorStop(0, "yellow");	//设置初始颜色
			grd.addColorStop(0.5, "cyan");	//设置中间颜色
			grd.addColorStop(1, "greenyellow");	//设置末端颜色
			
			ctx.fillStyle = grd;		//设置填充颜色
			ctx.fillRect(20, 20, 150, 100);		//填充矩形
		</script>
	</body>
</html>

4.2,径向渐变

径向渐变是指在两个指定圆的圆周之间放射性地插颜色值,使用图形上下文对象的createLinearGradient()绘制径向渐变:

context.createRadialGradient(xStart,yStart,radiusStart,xEnd,yEnd,radiusEnd)
    xStart为渐变开始圆的圆心横坐标
    yStart为渐变开始圆的圆心纵坐标
    radiusStart为开始圆的半径
    xEnd为渐变结束圆的圆心横坐标
    yEnd为渐变结束圆纵的坐标
    radiusEnd为结束圆的半径

在这个方法中,分别指定了两个圆的大小与位置。从第一个圆的圆心处向外进行扩散渐变,一直扩散到第二个圆的外轮廓处。在设定颜色时,与线性渐变相同,使用的是addColorStop方法进行设定。同样是需要设定0到1之间的浮点数来作为渐变转折点的偏移量。

同心圆渐变:var grd = con1.createRadialGradient(200, 200, 0, 200, 200, 200);
非同心圆渐变:var grd = con1.createRadialGradient(200, 200, 0, 300, 300, 200);
<html>
	<body>
		<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
			Your browser does not support the HTML5 canvas tag.
		</canvas>
		<script>
			var c = document.getElementById("myCanvas");
			var ctx = c.getContext("2d");
			var grd = ctx.createRadialGradient(75, 50, 5, 90, 60, 100);
			
			grd.addColorStop(0, "yellow"); //设置初始颜色
			grd.addColorStop(0.5, "cyan"); //设置中间颜色
			grd.addColorStop(1, "blue"); //设置末端颜色

			ctx.fillStyle = grd;
			ctx.fillRect(10, 10, 150, 100);
		</script>

	</body>
</html>

5,阴影,变形图形,图像

5.1,阴影

在HTML5中,使用canvas元素可以给图形添加阴影效果。添加阴影效果时,只需利用图形上下文对象的几个关于阴影绘制的属性就可以了,如下所示:

  • shadowColor:阴影的颜色,其默认值为完全透明的黑色。因此,如果没有把该属性设置为不透明,则阴影是不可见的。该属性只能设置为一个表示颜色的字符串,不能使用渐变或图案。使用半透明的阴影可以产生很逼真的阴影效果,因为透过阴影还能看到背景
  • shadowOffsetX:阴影在X轴的偏移量,单位为像素。默认值为0,阴影位于图形正下方,阴影是不可见的。大于0向右偏移,小于0向左偏移。阴影偏移量越大,产生的阴影也越大,同时会感觉绘制的图形在画布是浮得也越高
  • shadowOffsetY:阴影在Y轴的偏移量,单位为像素。默认值为0,阴影位于图形正下方,阴影是不可见的。大于0向下偏移,小于0向上偏移。阴影偏移量越大,产生的阴影也越大,同时会感觉绘制的图形在画布是浮得也越高
  • shadowBlur:阴影的模糊值。是一个与像素无关的值,被用于高斯模糊方程中,以便对阴影进行模糊化处理。默认值为0,表示产生一个清晰的阴影。该值越大,表示阴影越模糊。

根据canvas规范,只有在满足以下两个条件时,浏览器才会绘制阴影:1、指定了一个非全透明的shadowColor属性值;2、shadowOffsetX、shadowOffsetY、shadowBlur三个属性中,至少有一个属性的值不是0。

<html>
<link href="default.css" rel="stylesheet" />     
    <script>     
        var ctx = null; // global variable 2d context     
        var imageTexture = null;     
        window.onload = function() {     
            var canvas = document.getElementById("text_canvas");    
            var context = canvas.getContext('2d');     
                 
            // section one - shadow and blur     
            context.fillStyle="black";     
            context.fillRect(0, 0, canvas.width, canvas.height/4);     
            context.font = '60pt Calibri';     
                 
            context.shadowColor = "white";     
            context.shadowOffsetX = 0;     
            context.shadowOffsetY = 0;     
            context.shadowBlur = 20;     
            context.fillText("Blur Canvas", 40, 80);     
            context.strokeStyle = "RGBA(0, 255, 0, 1)";     
            context.lineWidth = 2;     
            context.strokeText("Blur Canvas", 40, 80);     
                 
            // section two - shadow font     
            var hh = canvas.height/4;     
            context.fillStyle="white";     
            context.fillRect(0, hh, canvas.width, canvas.height/4);     
            context.font = '60pt Calibri';     
                 
            context.shadowColor = "RGBA(127,127,127,1)";     
            context.shadowOffsetX = 3;     
            context.shadowOffsetY = 3;     
            context.shadowBlur = 0;     
            context.fillStyle = "RGBA(0, 0, 0, 0.8)";     
            context.fillText("Blur Canvas", 40, 80+hh);     
                 
            // section three - 下阴影     
            var hh = canvas.height/4 + hh;     
            context.fillStyle="black";     
            context.fillRect(0, hh, canvas.width, canvas.height/4);     
             for(var i = 0; i < 10; i++)     
            {    
                context.shadowColor = "RGBA(255, 255, 255," + ((10-i)/10) + ")";     
                context.shadowOffsetX = i*2;     
                context.shadowOffsetY = i*2;     
                context.shadowBlur = i*2;     
                context.fillStyle = "RGBA(127, 127, 127, 1)";     
                context.fillText("Blur Canvas", 40, 80+hh);     
            }     
                 
            // section four -  fade effect     
            var hh = canvas.height/4 + hh;     
            context.fillStyle="green";     
            context.fillRect(0, hh, canvas.width, canvas.height/4);     
            for(var i = 0; i < 10; i++)     
            {     
                context.shadowColor = "RGBA(255, 255, 255," + ((10-i)/10) + ")";     
                context.shadowOffsetX = 0;     
                context.shadowOffsetY = -i*2;     
                context.shadowBlur = i*2;     
                context.fillStyle = "RGBA(127, 127, 127, 1)";     
                context.fillText("Blur Canvas", 40, 80+hh);     
            }      
        }     
             
    </script>     
</head>     
<body>     
    <h1></h1>     
    <div id="my_painter">     
        <canvas id="text_canvas" width="800" height="800"></canvas>     
    </div>     
</body>     
</html>    

5.2,变形图形

【平移】移动图形的绘制主要是通过translate 方法来实现的:

context. translate(x, y);

translate 方法使用两个参数——x表示将坐标轴原点向左移动多少个单位,默认情况下为像素;y表示将坐标轴原点向下移动多少个单位。

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillRect(10,10,100,50);
ctx.translate(70,70);
ctx.fillRect(10,10,100,50);

第一个矩形起始坐标为(10,10) 调用了translate(70,70)后,新建了一个坐标系,原点改变,在第二个矩形开始画的起始坐标变为(10+70,10+70)。canvas会记录当前原点坐标,每当调用了translate(x,y)方法后新的坐标原点会在原先的基础上加上相应的值。

【矩阵变换】变换矩阵,这个矩阵是专门用来实现图形变形的,它与坐标一起配合使用,以达到变形的目的。当图形上下文被创建完毕时,事实上也创建了一个默认的变换矩阵,如果不对这个变换矩阵进行修改,那么接下来绘制的图形将以画布的最左上角的坐标原点绘制图形,绘制出来的图形也经过缩放、变形的处理,但是如果对这个变换矩阵进行修改,那么情况将会是不一样的。

transform(m11, m12, m21, m22, dx, dy)

【缩放】 使用图形上下文对象的scale方法将图形缩放:

context.scale(x,y);
    x是水平方向的放大倍数
    y是垂直方向的放大倍数。
将图形缩小的时候,将这两个参数设置为0到1之间的小数就可以了,例如0.5是指将图形缩小一半。

注释:如果您对绘图进行缩放,所有之后的绘图也会被缩放。定位也会被缩放。如果您 scale(2,2),那么绘图将定位于距离画布左上角两倍远的位置。

【旋转】使用图形上下文对象的rotate方法将图形进行旋转:

context.rotate(angle);
    angle是指旋转的角度,旋转的中心点是坐标轴的原点。旋转是以顺时针方向进行的,要想逆时针旋转时,将angle设定为负数就可以了。 

注意:canvas的转换不是针对整个canvas的,而是针对调用转换方法之后绘制的shapes 或 paths 旋转的中心是canvas的左上角(scale()的中心也是左上角),也就是点(0,0),但是通常我们需要的是围绕自己的中心进行旋转;转换的时候,需要把转换的中心点移到shape的自身的中心 移动中心点:context.translate(x + width/2, y + height/2); 中心点移动完后,修改fillRect的参数(x、y)context.fillRect(-0.5 * width, -0.5 * height);

5.3,绘制图像

图像绘制的基本步骤:

  • 读取图像文件
  • 在Canvas中进行绘制

图像读取前,首先创建Image对象,在Image对象的src属性中指定图像文件所在路径(URL)后就可以开始读取了。读取结束后,触发onload事件。基本语法下:

var image=new Image();
image.src="图像文件路径";
image.οnlοad=function(){/*图像读取时的处理*/}

使用Canvas上下文中的drawImage()方法将读取后的Image对象绘制在Canvas上,实际上是将Image对象中的图像数据输出到Canvas中。有三种drawImage()方法用于图像的绘制:

直接绘制:context.drawImage(image,dx,dy)     直接将读取的图像绘制在坐标(dx,dy)处
尺寸修改(resize):context.drawImage(image,dx,dy,dw,dh)   按照新的宽度(dw)与高度(dh)将图像绘制在坐标(dx,dy)处
图像截取:context.drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh)    将原图像的一部分截取出后再按指定尺寸绘制在Canvas上,从原图像的坐标(sx,sy)开始截取宽(sw)、高(sh)的部分图像,然后绘制在Canvas上的坐标(dx,dy)处,宽度为dw,高度为dh
<html>
	<body>
		<p>要使用的图像:</p>
		<img id="tulip" src="1.jpg" alt="The Tulip" />

		<p>画布:</p>
		<canvas id="myCanvas" width="500" height="300" style="border:1px solid #d3d3d3;background:#ffffff;">
			Your browser does not support the HTML5 canvas tag.
		</canvas>

		<script>
			var c = document.getElementById("myCanvas");
			var ctx = c.getContext("2d");
			var img = document.getElementById("tulip");
			ctx.drawImage(img, 10, 10);
		</script>

	</body>
</html>

5.4,像素处理

Canvas与SVG以及Flash稍有不同,绘制的图形/图像并不能作为对象操作。也就是说明使用stroke()或者fill()方法绘制的图形,既不能移动它也不能删除它。如果想操作绘制的图形/图像,使用SVG或者Flash实现比使用Canvas要好。

  • 使用图像上下文对象的getImageData方法来获取图像中的像素:
var imagedata = context.getImageData(sx,sy,sw,sh);
    sx、sy分别表示所获取区域的起点横坐标、起点纵坐标
    sw、sh分别表示所获取区域的宽度和高度。

ImageData对象是代表图像像素数据的对象,ImageData对象的属性:

  • imagedata.width:图像数据的宽度
  • imagedata.height:图像数据的高度
  • imagedata.data:图像数据(CanvasPixelArray类型)

Imagedata变量是一个CanvasPixelArray对象,具有heightwidthdata等属性。data属性是一个保存像素数据的数组,内容类似于“[r1,g1,b1,a1, r2,g2,b2,a2, r3,g3,b3,a3,…]”,其中,r1,g1,b1,a1为第一个像素的红色值,绿色值,蓝色值,透明值;r2,g2,b2,a2分别为第二个像素的红色值,绿色值,蓝色值,透明值,依次类推。data.length为所取得像素的数量。

  • 图像上下文对象的putImageData方法:
context.putImageData(imagedata,dx,dy[,dirtyX,dirtyY,dirtyWidth, dirtyHeight]);
    imagedata为前面所述的像素数组
    dx、dy分别表示重绘图像的起点横坐标,起点纵坐标
    后面dirtyX、dirtyY、dirtyWidth、 dirtyHeight这四个参数为可选参数,给出一个矩形的起点横坐标、起点纵坐标、宽度与高度,如果加上这四个参数,则只绘制像素数组中这个矩形范围内的图像。 

5.5,其他操作

局部放大:拖拽放大和hover放大,两种局部放大效果主要使用的均为canvas的getImageData以及putImageData。

图像美化:

  • 反色效果:把每一个像素的r, g, b颜色取反就行,也就是( 255 - 原来的值 )。
  • 调节亮度的强弱:在r、g、b、通道上加上一正值就是变亮,加上负值就是变暗。
  • 黑白效果(灰度图) 将彩色图片转换成黑白图片,原理:求r(data[i]), g(data[i+1]), b(data[i+2])三个通道的平均值,然后把这个平均值赋值给r, g, b。
  • 复古效果:将r, g, b按比例混合相加。
  • 蓝色蒙版:蓝色 蒙版就是让图片偏蓝色,将蓝色通道赋值为 r, g, b三原色的平均值,把绿色,红色通道设置为0,其他蒙版效果,只要设置对应的通道平均值,关闭其他通道即可。

图像平铺:所谓图像平铺就是用按一定比例缩小后的图像将画布填满,有两种方法可以实现该技术,一种是使用前面所介绍drawImage方法,另一种是使用图形上下文对象的createPattern方法:

context.createPattern(image,type);
    mage参数为要平铺的图像
    type参数的值必须是下面的字符串之一:no-repeat:不平铺,repeat-y:纵方向平铺,repeat:全方向平铺,repeat-x:横方向平铺。

图像裁剪:

  • 在路径绘图中使用了两种绘图方法,即用于绘制线条的stroke()方法和用于填充区域的fill()方法。关于路径的处理,还有一种方法叫做裁切方法clip()。
  • 该方法使用路径来对canvas 画布设置一个裁剪区域。因此,必须先创建好路径。路径创建完成后,调用clip方法设置裁剪区域。
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值