Canvas画图之中级篇

前段时间介绍了canvas画图的初级篇,今天接着介绍中级篇了...

一.绘制形状

绘制图形不仅仅是利用线条来实现绘图, 还可以有快捷的绘制图形的办法

1.绘制矩形

2.绘制圆弧

1 绘制矩形

绘制矩形的方法

CanvasRenderingContext2D.strokeRect

CanvasRenderingContext2D.fillRect

CanvasRenderingContext2D.rect

注意: rect 方法就是矩形路径, 还需要使用 fill 或 stroke 才可以看到效果. 因此一般使用 strokeRect 或 fillRect 直接可以看到结果.

清除矩形区域

CanvasRenderingContext2D.clearRect

1.1绘制矩形框

语法: CanvasRenderingContext2D.strokeRect( x, y, width. height )

描述:

用来绘制一个矩形. 比起直接使用 moveTo 和 lineTo 方法要简单许多.

该方法的前两个参数表示绘制矩形的左上角的坐标. 后两个参数表示这个矩形的宽高.

使用该方法不需要使用 moveTo 方法设置起始点, 也不需要调用 stroke 等绘画方法.

绘制的矩形支持 strokeStyle 设置颜色样式.

代码:

...

ctx.strokeStyle = ‘blue‘;

ctx.strokeRect( 100, 100, 200, 100 );

效果

1.2 绘制填充矩形

语法: CanvasRenderingContext2D.fillRect( x, y, width. height )

描述:

用来绘制一个矩形. 比起直接使用 moveTo 和 lineTo 方法要简单许多.

该方法的前两个参数表示绘制矩形的左上角的坐标. 后两个参数表示这个矩形的宽高.

使用该方法不需要使用 moveTo 方法设置起始点, 也不需要调用 stroke 等绘画方法.

绘制的矩形支持 fillStyle 设置颜色样式.

案例

...

ctx.fillStyle = ‘pink‘;

ctx.fillRect( 100, 100, 200, 100 );

效果

1.3清除矩形区域

语法: CanvasRenderingContext2D.clearRect( x, y, width, height )

描述:

用于清除画布中的矩形区域的内容.

参数 x, y 表示矩形区域左上角的坐标, width 与 height 表示矩形区域的宽高.

案例

...

ctx.fillRect( 100, 100, 150, 100 );

ctx.clearRect( 120, 120, 60, 60 );

注意:要清除矩形内部的区域时,clearRect的左上角坐标的x,y都要略大于矩形左上角坐标x,y值,否则清除的不完整。

效果

应用:可以利用绘制图形与清除矩形区域实现简单的动画

代码:

...

var x = 10, y = 10, oldx = 10, oldy = 10;

var width = 100, height = 50;

var timerId = setInterval(function () {

ctx.clearRect( oldx - 1, oldy - 1, width + 2, height + 2 );

ctx.strokeRect( x, y, width, height );

oldx = x;

oldy = y;

x += 4;

y += 2;

if ( oldy >= 200 ) {

// clearInterval( timerId );

x = 10, y = 10;

}

}, 20);

有时为了简单常常将整个画布都清除, 这样就不用每次计算清除的问题.

ctx.clearRect( 0, 0, cas.width, cas.height );

// 也可以设置画布宽度, 这样就会自动清除

cas.width = cas.width;

2.绘制圆弧

绘制圆弧的方法有:

CanvasRenderingContext2D.arc()

CanvasRenderingContext2D.arcTo()

2.1绘制圆弧

语法: CanvasRenderingContext2D.arc( x, y, radius. startAngle. endAngle, anticlockwise )

描述:

a.该方法用于绘制一段弧, 配合开始点的位置 与 stroke 方法或 fill 方法可以绘制扇形.

b.方法中的前两个参数 x, y 表示绘制圆弧的圆心坐标.

c.参数 radius 表示圆弧半径, 单位为弧度.

d.参数 startAngle 与 endAngle 表示开始到结束的角度. 角度以水平向右为 0 弧度, 顺时针为正方向.

e.参数 anticlockwise 表示是否采用默认的正向角度, 如果传入 true 表示逆指针为正. 该参数可选.

代码:

// 在 200, 200 的地方绘制一段半径为 100 的圆弧, 圆心角为 - PI / 2 到 PI / 4

...

ctx.arc( 200, 200, 100, -Math.PI/2, Math.PI/4 );

ctx.stroke();

// 为了方便看清楚结构, 绘制坐标轴

ctx.beginPath();

ctx.strokeStyle = ‘red‘;

ctx.moveTo( 50, 200 );

ctx.lineTo( 350, 200 );

ctx.moveTo( 200, 50 );

ctx.lineTo( 200, 350 );

ctx.moveTo( 200, 200 );

ctx.lineTo( 300, 300 );

ctx.stroke();

效果为:

2.1.1. 注意事项

使用 arc 绘图的时候, 如果没有设置 moveTo 那么会从开始的绘弧的地方作为起始点. 如果设置了 moveTo, 那么会连线该点与圆弧的起点.

如果使用 stroke 方法, 那么会从开始连线到圆弧的起始位置. 如果是 fill 方法, 会自动闭合路径填充.

例如

2.2绘制扇形动画

绘制扇形动画, 就是每隔几毫秒( 20 毫秒)擦除以前绘制的内容, 然后在以前绘制的基础上比以前多绘制一点东西. 这里多绘制的内容就是由角度决定. 比如一开始角度从 -Math.PI / 2 开始绘制. 那么每次角度都 +0.1, 直到 绘制到 Math.PI * 3 / 2 为止.

...

ctx.fillStyle = ‘green‘;

var startAngle = -Math.PI / 2,

angle = startAngle,

x = 200, y = 200,

r = 100;

var intervalId = setInterval(function () {

// 清除之前绘制的内容

ctx.clearRect( 0, 0, cas.width, cas.height );

// 角度增量

angle += 0.1;

// 判断是否停止计时器

if ( angle >= Math.PI * 3 / 2 ) {

clearInterval( intervalId);

angle = Math.PI * 3 / 2;

console.log( ‘绘制完成‘ );

}

// 绘制

ctx.moveTo( x, y );

ctx.arc( x, y, r, startAngle, angle );

ctx.fill();

}, 20);

2.3 绘制饼形图

绘制饼形图最大的特点是角度是叠加的. 开始从 -Math.PI/2 开始绘制, 达到执行角 x 后, 下一个区域从 x 开始绘制, 然后有到一个角 y 停下来. 如此反复到 Math.PI * 3 / 2 结束.

2.3.1. 三等分饼形图

绘制一个三等分的饼形图, 颜色使用 红, 绿, 蓝.

var x = 200, y = 200,

r = 100,

step = Math.PI * 2 / 3,     // 120 度一个区域

start = -Math.PI / 2,       // 起始角度

colors = [ ‘red‘, ‘green‘, ‘blue‘ ];

for ( var i = 0; i < 3; i++ ) {

ctx.beginPath();

ctx.moveTo( x, y );

ctx.fillStyle = colors[ i ];

ctx.arc( x, y, r, start, start+=step );

ctx.fill();

}

效果:

2.3.2 根据数据定义角度

根据数据源定义角度, 就是将所有的数据求和, 按照总和为 2 * Math.PI 的结论计算出每一个数据部分的弧度值. 同时颜色可以提前定义好.

var data = [ 456, 150, 321, 666 ];

//1.应该求得整个数组的和

var sum=0;

data.forEach(function (v) {

sum+=v;

})

//计算每个数字对应的比例 rdata表示对应的弧度数组

var rdata=data.map(function (v) {

//弧度/2PI=数字/数组数字和 故弧度=数字/数组数字和*2PI

return v*2*Math.PI/sum;

})

//准备颜色

//开始循环绘制

var startAngle=radian(-90);//饼形图一般默认是从-90度开始绘制的

var x=cas.width/2;

var y=cas.height/2;

var r=100;

rdata.forEach(function (v,i) {

ctx.beginPath();

ctx.moveTo(x,y);

ctx.fillStyle=colors[(i+1)*11];//为了使各部分选择的颜色不那么相近

ctx.arc(x,y,r,startAngle,startAngle+=v);

ctx.fill();

})

效果为:

2.4. 绘制相切弧

语法: CanvasRenderingContext2D.arcTo( x1, y1, x2, y2, radius )

描述:

该方法用于绘制圆弧

绘制的规则是当前位置与第一个参考点连线, 绘制的弧与该直线相切.

同时连接两个参考点, 圆弧根据半径与该连线相切

例如有一个起始点 ( 100, 100 ), 那么绘制其点. 颜色设置为红色.

ctx.fillStyle = ‘red‘;

ctx.fillRect( 100 - 4, 100 - 4, 8, 8 );

然后两个参考点分别为 ( 100, 300 ) 和 ( 300, 300 ), 绘制出该点

ctx.fillRect( 100 - 4, 300 - 4, 8, 8 );

ctx.fillRect( 300 - 4, 300 - 4, 8, 8 );

连接两个参考点

ctx.beginPath();

ctx.strokeStyle = ‘red‘;

ctx.moveTo( 100, 300 );

ctx.lineTo( 300, 300 );

ctx.stroke();

调用 arcTo 方法绘制圆弧. 记得将起始点设置为 ( 100, 100 )

ctx.beginPath();

ctx.strokeStyle = ‘blue‘;

ctx.moveTo( 100, 100 );

ctx.arcTo( 100, 300, 300, 300, 100 );

ctx.stroke();

效果为:

提示: 使用该方法可以使用圆弧连接两条直线, 而不用计算复杂的起始角度与结束角度. 因此多用于绘制圆角矩形。

3.绘制文本

绘制文本的方法

CanvasRenderingContext2D.fillText()

CanvasRenderingContext2D.strokeText()

CanvasRenderingContext2D.measureText()

文本样式

CanvasRenderingContext2D.font

CanvasRenderingContext2D.textAlign

CanvasRenderingContext2D.textBaseline

3.1. 绘制文字

语法:

CanvasRenderingContext2D.strokeText( text, x, y[, maxWidth] )

CanvasRenderingContext2D.fillText( text, x, y[, maxWidth] )

描述:

这两个方法的功能都是在给定的 x, y 坐标下绘制文本内容.

stroke 绘制描边文字, 文字内空心. fill 绘制填充文字, 即实心文字.

最后一个参数可选, 用于限制文字的总宽. 特殊条件下, 系统会自动调整文字宽度与大小以适应该参数限制.

3.2计算文本尺寸

语法: CanvasRenderingContext2D.measureText()

描述:

该方法返回一个文本尺寸对象, TextMetrics 对象.

TextMetrics 对象属性很多, 常用的 width 属性可以获取文字的宽度.

3.3. 设置文字属性

3.3.1. 设置文字字体

语法: CanvasRenderingContext2D.font = value

描述:

该属性用于设置绘制字体的各种信息, 与 CSS 语法一致, 设置字体形状, 样式, 字号粗细等.

其顺序可以是: style | variant | weight | size/line-height | family.

默认值为 10px sans-serif

修改字号后查看 strokeText 与 fillText 的区别

...

ctx.font = ‘50px 黑体‘;

ctx.strokeRect( 100, 100, 200, 50 );

ctx.strokeText( ‘Hello JK‘, 100, 100 );

ctx.strokeRect( 100, 200, 200, 50 );

ctx.fillText( ‘Hello JK‘, 100, 200 );

效果为:

3.3.2. 设置字体水平对齐方式

语法: CanvasRenderingContext2D.textAlign = value

描述:

该属性用于设置文字的水平对齐方式. 设置文字居中, 靠左右对齐等.

该属性可以设置的值有: start( 默认 ), end, left, right, center.

start 表示根据参考基准点的垂直直线左靠对齐

end 表示根据参考基准点的垂直直线右靠对齐

left 与 right 就是左对齐与右对齐的意思

center 就是居中的意思.

3.3.3. 设置字体垂直对齐方式

语法: CanvasRenderingContext2D.textBaseline = value

描述:

该方法设置文字在垂直方向上的对齐方式.

该属性可以取值: top, middle, bottom, hanging, alphabetic, ideographic

基于参考点的直线, 其中 top, middle, buttom 分别表示靠上, 居中, 靠下对齐.

alphabetic 表示字母基线, 类似于英文字母的对齐方式. 例如 a, g, f 等字母.

ideographic 表意对齐. 使用字母对齐中超出的字母为参考. 即比字母基线略靠下.

所有的对齐方式是根据文字特点相关的. 对于中文主要使用的还是 top, bottom 和 middle.

top, middle, bottom 使用的较多

alphabetic 表示字母参考线, ideographic 会比它低一点, hanging 表示悬挂.

4.绘制图片

绘制图像虽然只有一个 drawImage 函数, 但是该函数有多重参数形式.

CanvasRenderingContext2D.drawImage( img, dx, dy ).(三参数)

CanvasRenderingContext2D.drawImage( img, dx, dy, dWidth, dHeight ).(五参数)

CanvasRenderingContext2D.drawImage( img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight ).(九参数)

4.1. 绘制简单图像

语法: CanvasRenderingContext2D.drawImage( img, dx, dy )

描述:

使用三个参数, 允许在画布上的任意位置绘制图片.

参数 img 是指图片对象. 可以是 img 标签, 或者是 video 标签, 已经另一个 canvas 等.

提示:需要注意的是如果直接添加 img 对象是不可以的, 需要等待其加载,因为加载图片需要时间, 因此将绘制的方法放在 onload 事件中.

这里使用 new Image() 与 document.createElement( ‘img‘ ) 是一样的.

4.2. 在指定区域内绘制图像

当图片比较大的时候, 如果使用这样的方式绘图, 那么图片可能会完全覆盖画布. 例如:

因此, 需要将其控制在一个矩形区域内绘制.

语法: CanvasRenderingContext2D.drawImage( img, dx, dy, dWidth, dHeight )

描述:

参数 dWidth, dHeight 表示绘制的矩形区域. 绘制的 dx, dy 坐标决定了开始.

该方法绘制的图像会在指定范围内被压缩显示.

将上面的图绘制在 100 * 100 的范围内.

...

ctx.drawImage( img, 100, 100, 100, 100 );

效果

如果希望正常显示, 需要固定一个宽度或者高度, 然后根据比例计算出另一个值. 这里假定高度是 100. 计算宽度后绘图.

...

var heigth = 100, width;

img.onload = function () {

width = img.width * height / img.height;

ctx.drawImage( img, 100, 100, width, height );

};

效果

4.3. 绘制任意图像

类似于 CSS 中处理按钮等小图标的技巧, 将很多的效果图集中在一张 png 格式的背景透明的图片中, 这样可以提高效率也便于维护. 那么 drawImage 同样支持该方式绘图. 在画布中的指定位子与指定区域内, 绘制图片中的某个矩形区.

语法: CanvasRenderingContext2D.drawImage( img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight )

描述: 这里的带有 s 前缀的参数就是指图源的矩形区域.

例如将图片的 ( 100, 100, 300, 200 ) 处的内容绘制到页面的 ( 100, 100, 300, 200 ) 的位置.

‘‘‘

ctx.drawImage( img, 100, 100, 300, 200,  100, 100, 300, 200 );

效果

4.4. 绘制动画

有了图片部分绘制的功能, 我们就可以尝试绘制动画了. 准备一张图片

然后开始的时候绘制第一行的第一张图. 计算它的坐标与宽高

var img = new Image();

img.src = ‘./imgs士兵(1).png‘

img.onload = function () {

var width = img.width / 4;

var height = img.heigth / 4;

// 第一张图的顶点是 0, 0, 宽高是 width, height

};

那么第一行的第二张图就是 ( 0, width, width, height ), 第三张就是 ( 0, width * 2, width, height ). 因此第一行的第 i 张图就是

var x = 0;

var y = width * ( i - 1 );

同理得到, 第 j 列的 x 坐标是 height * ( j - 1 )

现在绘制第一张图

...

var img = new Image();

img.src = ‘./imgs/士兵(1).png‘

img.onload = function () {

var width = img.width / 4;

var height = img.height / 4;

ctx.drawImage( img, 0, 0, width, height, 100, 100, width, height );

};

现在要求, 每隔 200 毫秒就切换一张图片, 现在只考虑第一行的图片.

...

var img = new Image();

img.src = ‘./imgs/士兵(1).png‘

img.onload = function () {

var width = img.width / 4;

var height = img.height / 4;

var i = 0;

setInterval(function () {

ctx.clearRect( 0, 0, cas.width, cas.height );

ctx.drawImage( img, width * (i++ % 4), 0, width, height, 100, 100, width, height );

}, 200 );

};

时间: 2024-10-08 10:33:32

Canvas画图之中级篇的相关文章

canvas画图——初级篇

         canvas画图之初级篇 小女子准备将canvas画图分为初级篇,中级篇和高级篇来介绍,读者们不要着急哦. 初级篇 一.首先什么是canvas呢? canvas 是 HTML5 提供的一个用于展示绘图效果的标签. canvas 原意画布, 帆 布. 在 HTML 页面中用于展示绘图效果. 最早 canvas 是苹果提出的一个方案, 今天已经在大多数浏览器中实现. canvas 英 ['kænv?s]  美 ['kænv?s]   帆布 画布 二.让我们先来了解下canvas的基

html5 Canvas画图3:1px线条模糊问题

点击查看原文地址: html5 Canvas画图3:1px线条模糊问题 本文属于<html5 Canvas画图系列教程> 接上一篇canvas画线条教程 上次我们讲到,canvas有时候会出现1像素的线条模糊不清且好像更宽的情况,如下图: 这样的线条显然不是我们想要的. 这篇文章的目的就是弄清楚里面的原理,以及解决它. 大家都知道屏幕上最小的显示尺寸就是1像素,虽然小于1像素的东西可能显示不出来,但计算机可不管,他会试着画一下. 其实像素终究来说也是一个单位,假如我们把画布放大到足够大,足以看

[转]html5 Canvas画图教程(6)—canvas里画曲线之arcTo方法

arc与arcTo,从名字都能看出来相似.arcTo也是画曲线的方法,而且他画出的曲线也是正圆的一段弧线.但他的参数和arc简直是不共戴天~ ctx.arcTo(x1,y1,x2,y2,radius);arcTo的参数中包括两个点,而且这两个点中并没有表示圆心的点,仅仅最后的参数是圆的半径,表示arcTo和圆有那么点关系. 网上关于arcTo的文章很少,好不容易找到一篇还是外国的:而且canvas画图木有直观工具,只能靠猜,arcTo害我猜了半天.. 为了直观的描述,我采取了一种辅助办法:arc

Canvas画图在360浏览器中跑偏的问题

问题描述,canvas画图的js代码中编写的是画正方形的代码,结果在360浏览器上变成了长方形,不知道怎么回事,请问各位大神是否遇到过此类问题? 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 5 <title></title> 6

Farseer.net轻量级开源框架 中级篇:数据库切换

导航 目   录:Farseer.net轻量级开源框架 目录 上一篇:Farseer.net轻量级开源框架 中级篇: 动态数据库访问 下一篇:Farseer.net轻量级开源框架 中级篇: SQL执行报告 上文中讲述了,在项目运行过程中,如何通过代码动态改变数据库的访问,这种方式更加倾向于实体类相同,有多个相同的表结构. 本篇中讲述的是,如何快速切换不同的数据库.比如你现在使用在使用SqlServer 哪天数据库老板心血来潮,让你换成Oracle了,怎么办? 这种数据库的切换在ORM中能明显突出

canvas 画图工具 -- CanvasDraw

最近有些项目中用到了canvas画图: 为了方便封装了一下: 他的强大之处是 处理了各种偏针的问题: 1,css 强制宽高的变形 造成的偏针 2,给canvas加边 造成的偏针 3,上层父级缩放 造成的偏针 ( 前两种函数自行校正,第3种要传参) 更多去 github 吧,记得点赞谢谢 CanvasDraw:https://github.com/songyijian/CanvasDraw var c2=new CanvasDraw('#canvas2',{ 'attr':{'width':400

Android中级篇之百度地图SDK v3.5.0-一步一步带你仿各大主流APP地图定位移动选址功能

定位+移动选址 百学须先立志-学前须知: 我们经常在各大主流APP上要求被写上地址,如百度外卖.爱鲜蜂收货地址等等:其中他们大多数是可以让我们在地图上移动选址.就如下面这段GIF演示的一样: 尽信书,不如无书-能学到什么? 1.地图状态MapStatus类及监听setOnMapStatusChangeListener 2.定位LocationClient类 3.反地理编码GeoCoder类 工欲善其事必先利其器-申请Key 百度地图访问应用(AK)申请地址:http://lbsyun.baidu

在Eclipse中使用JUnit4进行单元测试(中级篇)【转】

我们继续对初级篇中的例子进行分析.初级篇中我们使用Eclipse自动生成了一个测试框架,在这篇文章中,我们来仔细分析一下这个测试框架中的每一个细节,知其然更要知其所以然,才能更加熟练地应用JUnit4. 一.     包含必要地Package 在测试类中用到了JUnit4框架,自然要把相应地Package包含进来.最主要地一个Package就是org.junit.*.把它包含进来之后,绝大部分功能就有了.还有一句话也非常地重要“import static org.junit.Assert.*;”

Farseer.net轻量级开源框架 中级篇:动态数据库访问

导航 目   录:Farseer.net轻量级开源框架 目录 上一篇:Farseer.net轻量级开源框架 中级篇: 自定义配置文件 下一篇:Farseer.net轻量级开源框架 中级篇: 数据库切换 说到动态数据库的访问,不得不说的是,我们的实体类,是如何找到数据库配置并访问的呢? 回顾下我们的Users类: 1 [DB(Name = "Members_User")] 2 public class Users : BaseModel<Users>; 这里有个DB的特性,其