HTML5用度爱心鱼游戏体系第二部分,canvas图形绘制之星空

canvas图形绘制之星空、噪点与谷雾效果

2016/06/07 · HTML5 · 1
评论 ·
Canvas

原稿出处:
张鑫旭(@张鑫旭)   

变形

在打听变形从前,先通晓意况。

  • 状态

canvas
的情状就是当下画面应用的享有样式和变形的一个快照,用来操作那些场馆有七个绘制复杂图形时不可或缺的法子:save()restore()
。save()用来保存当前状态,restore()用来还原刚才保存的情况。他们都足以频繁调用。

ctx.fillStyle = 'black';
ctx.fillRect(20, 20, 150, 150);
ctx.save();  //保存当前状态
ctx.fillStyle= '#fff';
ctx.fillRect(45, 45, 100, 100);
ctx.restore();    //恢复到刚才保存的状态
ctx.fillRect(70, 70, 50, 50);
  • 位移translate(x, y)

translate办法,它用来移动 canvas 和它的原点到一个不等的职分。

demo:

var ctx = document.getElementById('canvas').getContext('2d');
for(var i = 1; i< 4; i++) {
    ctx.save();   //使用save方法保存状态,让每次位移时都针对(0,0)移动。
  ctx.translate(100*i, 0);
  ctx.fillRect(0, 50, 50, 50);
  ctx.restore();
}
  • 旋转 rotate(angle)

    rotate 它用来以原点为主导旋转:
    旋转的角度(angle),它是顺时针方向的,以弧度为单位的值。

ctx.rotate(Math.PI * 2)     //参照原点顺时针旋转360度

demo:

ctx.translate(75,75);    //把原点移动到(75, 75);
for (var i=1; i<6; i++){       // 从里到外一共6圈
  ctx.save();
  ctx.fillStyle = 'rgb('+(50*i)+','+(255-50*i)+',255)';
  for (var j=0; j<i*6; j++){     // 每一圈有i*6个圆点
    ctx.rotate(Math.PI*2/(i*6));
    ctx.beginPath();
    ctx.arc(0,i*12.5,5,0,Math.PI*2,true);
    ctx.fill();
  }
  ctx.restore();
}
  • 缩放 scale

ctx.scale(x, y);     //基于原点缩放,x、y是两个轴的缩放倍数

demo:

var ctx = document.getElementById('canvas').getContext('2d');
ctx.fillStyle = 'red';
ctx.scale(0.8, 1.2);
ctx.beginPath();
ctx.arc(75, 75, 60, 0, Math.PI * 2);
ctx.fill();
  • 变形 transforms

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

m11:水平方向的缩放

m12:水平方向的偏移

m21:竖直方向的晃动

m22:竖直方向的缩放

dx:水平方向的移动

dy:竖直方向的运动

上边开头真的的付出一个小游戏

 本文将延续介绍canvas的效劳,浮现如何绘制更扑朔迷离的图样(包含圆弧和曲线),如何采纳剪裁区域来限制操作以及怎么样绘制文本。依然介绍能够运用在画布上的特效和转换,蕴涵影子、透明度、旋转和坐标重映射。

一、三合一

八个功效合成一篇小说。

有多少个小伙伴问我,为啥不开个公众号,现在都是移动时代,你博客文章写好后,公众号再复制一份,花不了多久,同时传播方便飞快,打赏方便神速,明显低费用高收益。

从眼前来看,就像的确如此。

可是,就我个人而言,行为和处事准则总是遵守内心的直觉和大方向的教导。说不上具体的道理,就是认为,文章的输出源假如持续一个,久远来看,带来的无人问津损耗一定要高于长期的已知收益。

取巧的业务多慎思而克己,就好比本文内容,实际上,多个不等的canvas效果,直接分3篇来写,凑个小说数,增添点浏览量其实也是无可厚非的。然,想了想,有点不像自己的style,内心真正的和谐并不期望团结如此做,于是,就3个职能合体为一篇小说。

不容小部分的抓住,让自己过得更轻松。

正文的3个功效都是源自我近年来做的多少个实在的档次,是canvas领域基本入门的有些职能。代码我都尤其重新梳理了下,要求注释也都丰富去了,方便我们的学习。然后,如若你有不懂的地点,请不要来问我,没错,是不要,我并不欢迎您找我来互换,自己一点一点去弄领悟。因为,若是连这么基本的canvas效果都不精晓,我真的也帮不了你怎么着。倒不是说腾不出时间,而是腾不出精力,每一日新浪私信还有邮箱找我的人还挺多,实在应接不暇。

动画

一帧一帧的来渲染那几个因素,而且那个因素每一帧的岗位都不均等,大家的肉眼看看的就是动画片了。完毕起来也很有利,js提供了多少个主意:setTimeout 和setInterval都得以兑现,可是一个有逼格的程序员已毕动画是不会用那七个法子的,而是用requestAnimationFrame这几个主意。有如何分别呢?上边简单做个相比较。

  • setInterval(myFun, 10);
    意思是隔一飞秒执行一个myFun函数,可是那样就有一个标题了,比如自己myFun函数里面绘制的东西相比较耗时,而10ms之内还并未完全绘制出来,不过那段代码强制1ms过后又开头绘制下一帧了,所以就会油但是生丢帧的题目;反之,即使时光设置太长,就会产出画面不流畅、视觉卡顿的问题。
  • requestAnimationFrame(myFun);
    要是大家那样写,又是怎么看头吧?意思是基于早晚的小时距离,会自行执行myFun函数来展开绘图。那么些”一定的时刻距离”就是依照浏览器的性质如故网速快慢来控制了,不言而喻,它会有限帮衬你绘制完这一帧,才会绘制下一帧,保障品质的同时,也确保动画的余音绕梁

中央步驟:

  1. 清空 canvas

只有接下去要画的内容会全盘充满 canvas
(例如背景图),否则你须求清空所有。最简便易行的做法就是用 clearRect 方法。

  1. 保存 canvas 状态

假诺您要改变一些会改变 canvas
状态的装置(样式,变形之类的),又要在每画一帧之时都是原始状态以来,你须求先保存一下。

  1. 绘制动画图形(animated shapes)

这一步才是重绘动画帧。

  1. 恢复 canvas 状态

设若已经保存了 canvas 的图景,可以先过来它,然后重绘下一帧。

此处首先介绍canvas所有接口的运用。包蕴beginpath,closePath,linejoin,miterlimit,translate,rotate,scale,linecap。

1. 用路径绘图

二、canvas图形效果之旋转星空

澳门葡京 1

图是死的,效果是活的,IE9+浏览器下,您可以狠狠地方击那里:canvas落成的转动星空效果demo

会见到地球上方会有成千成万星星在逐步地绕着地球转啊转,星星在闪啊闪。

像那类密集型canvas效果,一般离不开上边那多少个根本字:实例,随机,变化与重绘,requestAnimationFrame。

规律就是:

  1. 先画一个岗位透明度随机的静态的星星实例对象;
  2. 有一个方可改变简单地方和透明度的draw方法;
  3. 定时器跑起来,画布不停地解除与绘图,动画效果落成!

规律很粗略。

本例子落成的2个困难在于:

  1. 月明星稀
    澳门葡京,星星垂直方向实际上是个伪随机,越接近地球,星星越密集,而越往上,越稀疏。其算法如下:
JavaScript

var getMinRandom = function() { var rand = Math.random(); //
step的大小决定了星星靠近地球的聚拢程度, // step = Math.ceil(2 /
(1 - rand))就聚拢很明显 var step = Math.ceil(1 / (1 - rand)); var
arr = \[\]; for (var i=0; i&lt;step; i++) { arr.push(Math.random());
} return Math.min.apply(null, arr); };

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f4a6436b2b195965046-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f4a6436b2b195965046-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f4a6436b2b195965046-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f4a6436b2b195965046-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f4a6436b2b195965046-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f4a6436b2b195965046-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f4a6436b2b195965046-7">
7
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f4a6436b2b195965046-8">
8
</div>
<div class="crayon-num" data-line="crayon-5b8f4a6436b2b195965046-9">
9
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f4a6436b2b195965046-10">
10
</div>
<div class="crayon-num" data-line="crayon-5b8f4a6436b2b195965046-11">
11
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f4a6436b2b195965046-12">
12
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f4a6436b2b195965046-1" class="crayon-line">
var getMinRandom = function() {
</div>
<div id="crayon-5b8f4a6436b2b195965046-2" class="crayon-line crayon-striped-line">
    var rand = Math.random();
</div>
<div id="crayon-5b8f4a6436b2b195965046-3" class="crayon-line">
    // step的大小决定了星星靠近地球的聚拢程度,
</div>
<div id="crayon-5b8f4a6436b2b195965046-4" class="crayon-line crayon-striped-line">
    // step = Math.ceil(2 / (1 - rand))就聚拢很明显
</div>
<div id="crayon-5b8f4a6436b2b195965046-5" class="crayon-line">
    var step = Math.ceil(1 / (1 - rand));
</div>
<div id="crayon-5b8f4a6436b2b195965046-6" class="crayon-line crayon-striped-line">
    var arr = [];
</div>
<div id="crayon-5b8f4a6436b2b195965046-7" class="crayon-line">
    for (var i=0; i&lt;step; i++) {
</div>
<div id="crayon-5b8f4a6436b2b195965046-8" class="crayon-line crayon-striped-line">
        arr.push(Math.random());
</div>
<div id="crayon-5b8f4a6436b2b195965046-9" class="crayon-line">
    }
</div>
<div id="crayon-5b8f4a6436b2b195965046-10" class="crayon-line crayon-striped-line">
 
</div>
<div id="crayon-5b8f4a6436b2b195965046-11" class="crayon-line">
    return Math.min.apply(null, arr);       
</div>
<div id="crayon-5b8f4a6436b2b195965046-12" class="crayon-line crayon-striped-line">
};
</div>
</div></td>
</tr>
</tbody>
</table>

很大概率会返回一个数值偏小的值,于是,就可以有“月明星稀”的分布效果了。
  1. 圆弧轨迹
    骨子里很粗略,我们套用高中时候学的圆方程式就足以了,如下注释截图所述:
    澳门葡京 2那下标题就不难了,已知a,b,
    求y相对于x的函数表达式……

高级动画

动画重如若requestAnimationFrame方法,现在大家来促成一个在画布内滚动的实例

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var ball = {    //小球属性,原点位置,速度,半径等。
    x: 100,  
    y: 100,
    vx: 4,
    vy: 2,
    radius: 20,
    color: 'blue',
    draw: function() {
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, true);
        ctx.closePath();
        ctx.fillStyle = this.color;
        ctx.fill();
    }
};
function draw() {
    ctx.clearRect(0,0, canvas.width, canvas.height);    //绘制之前清除整个画布
    ball.draw();   //在画布中绘制小球
    ball.x += ball.vx;   //改变小球位置坐标
    ball.y += ball.vy;   //改变小球位置坐标
    if (ball.y + ball.vy > canvas.height-15 || ball.y + ball.vy < 15) {   //边界判断
        ball.vy = -ball.vy;
    }
    if (ball.x + ball.vx > canvas.width-15 || ball.x + ball.vx < 15) {   //边界判断
        ball.vx = -ball.vx;
    }
    window.requestAnimationFrame(draw);   //循环执行
}
draw();

简单概括一下这个实例的实现思想:

开创一个小球对象,包涵一个制图自己的方法。在全路画布中绘制那一个小球,然后在下三次绘制此前,先消除整个画布,改变小球的次第属性(包涵了逻辑,比如边界的论断),然后重新绘制五遍,从而落成了动起来的成效。

一旦你把地方代码中的ctx.clearRect(0,0, canvas.width, canvas.height);交流上面这样:

ctx.fillStyle = 'rgba(255,255,255,0.3)';
ctx.fillRect(0, 0, canvas.width, canvas.height);

就可以博得渐变尾巴的效应,大约意思就是使用半透明的白色背景填充画布来代替直接清除这个画布,从而完结了想要的法力。

HTML5用度爱心鱼游戏体系第二部分,canvas图形绘制之星空。本课起始前,要了然canvas的成立,怎么样绘制直线,多边形,弧线,圆。

途径本质上是一组独立的线条(被称为子路径),它们组成到一块组成图形。我们绘制子路径的章程如同用笔在纸上画图一律,笔尖不偏离纸面:画布上的每一便条路径都以上一条的终点作为起源。上面显示了绘图基本途径的形式:

三、canvas图形效果之雪花噪点效果

澳门葡京 3

图是死的,效果那里也是死的,但并不妨碍大家零距离围观,您可以狠狠地方击那里:canvas达成的噪点效果demo

鉴于那里是静态的,所以但从那点来看,似乎比上边星空不难。不过,倘若单独看绘制一帧,那那里的噪点要比上边的星空要困难些,最大的难处在于对质量的把控。

那般说吧,上边的星空,总共最多就400个点(白色的有数),不过,那里的噪点,例如,demo中画布大小(那自己的电话机举例)是1920*500,其中,噪点大小是1像素*1像素,总共就有960000个绘制点,明显跟400个点完全不是一个数据级的,假若我们实在一个一个绘制下来,肯定,就连Chrome这么牛步的浏览器也会深感到明确的卡顿,如何优化如何绘制呢?

那就是本例子已毕的难关:

  1. 数码与品质
    本人那边是那般处理的,即便最后的噪点大小是1920*500,然而,我们实在是由N块300*150的小的像瓷砖同样的小方块拼起来的。话句话说,我骨子里只绘制了45000个点,比960000分明要小了20倍还不止。那样,既满意了成效,又确保了质量。

具体完成原理为:

  1. 始建一个canvas,绘制一个300*150肆意噪点图形;
  2. 把那里所有噪点的canvas以画布方式在绘制到页面上的大canvas上;

说得canvas绘图,不得不提一下可怜常用的一个drawImage()艺术,语法如下:

context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);

1
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);

次第参数示意为(网上的讲述都是直译,很隐晦,我那边再次陈述了下):

参数 描述
img 用来被绘制的图像、画布或视频。
sx 可选。img被绘制区域的起始左上x坐标。
sy 可选。img被绘制区域的起始左上y坐标。
swidth 可选。img被绘制区域的宽度。
sheight 可选。img被绘制区域的高度。
x 画布上放置img的起始x坐标。
y 画布上放置img的起始y坐标。
width 可选。画布上放置img提供的宽度。(伸展或缩小图像)
height 可选。画布上放置img提供的高度。(伸展或缩小图像)

本例的小的噪点区块就是透过drawImage()主意被平铺到大的canvas元素上的。

像素操作

假如大家想对一个canvas画布举办如下操作:获取每一个点的音信,对每一个坐标点举行操作。那大家就必要了然一下ImageData对象了。

ImageData对象(由getImageData方法获得的)中存储着canvas对象实际的像素数量,它含有以下多少个只读属性:

  • width

图表宽度,单位是像素。

  • height

图片中度,单位是像素。

  • data

Uint8ClampedArray类型的一维数组,包涵着RGBA格式的整型数据,范围在0至255之间(包蕴255)。简单讲,就是一个数组,每七个因素存储一个点的颜料新闻,那多少个要素分别对应为R、G、B、A的值(知道颜色取值的一眼就通晓了,不亮堂的也没提到,前面有实例,一看就了然)。

愈来愈错综复杂的动画片进程,还要等绘制学完事后,才能拿下。

澳门葡京 4

四、canvas图形效果之气团雾缭绕效果

澳门葡京 5

图是死的,效果是活的,IE9+浏览器下,您可以狠狠地方击这里:canvas完结的云烟缭绕效果demo

本例子,效果看上去要更酷一些,实际上,从技术层面讲,跟上面的星空旋转效果大概如出一辙,可能还要比星空更简多美滋(Dumex)些,因为其活动轨迹直来直往,不要求转圈圈。

那为啥看起来更酷呢,首要在于感觉上坡雾很难去模拟。

毋庸置疑,辐射雾确实很难用代码间接绘制出来,实际上,那里的云烟,是一个png图片,是接纳画笔在PS里绘制导出来的。

旋转星空的事例,我们是运用canvas的fillRect方法绘制了一定量,而本例子,则是应用方面提到的drawImage()方式把平流雾图片绘制进来了。

其余的位移啊,透明度变化什么的,原理都是近似。

本例子的难处首要在于模拟是或不是充分真实:

  1. 高处不胜寒
    越往上,气团雾越淡,实际上就是越走近上方,透明度越低;
// 越靠近边缘,透明度越低 // 纵向透明度变化要比横向的明显 this.alpha
= (1 - Math.abs(canvasWidth\*0.5 - this.x) / canvasWidth) \* (0.7 -
Math.abs(canvasHeight\*0.5 - this.y) / canvasHeight);

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f4a6436b3d419634939-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f4a6436b3d419634939-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f4a6436b3d419634939-3">
3
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f4a6436b3d419634939-1" class="crayon-line">
// 越靠近边缘,透明度越低
</div>
<div id="crayon-5b8f4a6436b3d419634939-2" class="crayon-line crayon-striped-line">
// 纵向透明度变化要比横向的明显
</div>
<div id="crayon-5b8f4a6436b3d419634939-3" class="crayon-line">
this.alpha = (1 - Math.abs(canvasWidth*0.5 - this.x) / canvasWidth) * (0.7 - Math.abs(canvasHeight*0.5 - this.y) / canvasHeight);
</div>
</div></td>
</tr>
</tbody>
</table>
  1. 缭绕
    所谓“缭绕”,就是运动看似不持有规律性。要明了,凡事有轨道有套路的移位都是有规律性地,你说那冰雾上上下下,左左右右运动太过头规律,效果就会缩减,可是,真的没有规律又不佳通过代码控制移动轨迹。因而,为了搞到一个像样缭绕效果的移位函数,还真是烧了不可胜言脑细胞。
创建ImageData对象

去创建一个新的,空白的ImageData对像,你应当会动用createImageData()方法:

var myImageData = ctx.createImageData(width, height);

地点代码创立了一个新的有血有肉特定尺寸的ImageData对像。所有像素被预设为透明黑。

每个接口一个小的示范性程序,启示如何将那些接口使用在真正的条件中。

制图一条路径的要旨顺序如下:

五、canvas动效与结语

正文五个例证都是canvas 2D效果,是入门学习非常好的例证。

canvas万分适合完毕密集型图形和动画,可以把品质优势给发挥出来,因为就是一块画布渲染;别的一些就是省流量,比方说第2个例证的噪点效果,假使是千篇一律效果1920*500的png图片,科科,我更加保存了下,286K,1K的代码PK
286K的图纸,显著是完爆啊!

canvas还支持3D效果,也就是webGL, 亦称3D Canvas graphics,
IE11+支持,目前Android
4.*擅自版本都还不援救,业内资深的相关库就是threejs了。

只是,我没探讨过,也没兴趣,不是自我的方向。

好了,就这个,感谢阅读。

1 赞 7 收藏 1
评论

澳门葡京 6

得到像素数据

为了获得一个暗含画布场景像素数据的ImageData对像,你可以用getImageData()方法

var myImageData = ctx.getImageData(left, top, width, height);

成立的myImageData对象就有width、height、data七个特性的值了。看上边这几个实例:

html:

<div id="color">hover处的颜色</div>
<canvas id="myCanvas" width="300" height="150"></canvas>

js:

var can = document.getElementById('myCanvas');
var ctx = can.getContext('2d');
var img = new Image();
    img.src = "***.jpg";
ctx.drawImage(img, 0, 0);
var color = document.getElementById('color');
function pick(event) {
    var x = event.layerX;
    var y = event.layerY;
    var area = ctx.getImageData(x, y, 1, 1);  //创建ImageData对象
    var data = area.data;   //获取data属性(一个存储颜色rgba值的数组)
    var rgba = 'rgba(' + data[0] + ',' + data[1] + ',' + data[2] + ',' + data[3] + ')';
    color.style.color =  rgba;
    color.textContent = rgba;
}
can.addEventListener('mousemove', pick);

Canvas基础回归:

* 调用 beginPath方法;

在万象中写入像素数据

你可以用putImageData()艺术去对现象进行像素数据的写入

ctx.putImageData(myImageData, x, y);  //在画布的(x, y)点开始绘制myImageData所存储的像素信息。

从而我们得以把收获到的像素音讯进行拍卖,然后再另行绘制,就收获了新的图样。看看上面那几个实例:

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = '***.jpg';
ctx.drawImage(img, 0, 0);
var imageData = ctx.getImageData(0,0,canvas.width, canvas.height);  //获取ImageData
var colors = imageData.data;  //获取像素信息
function invert() {
    for (var i = 0; i < colors.length; i += 4) {  //四个为一组
        colors[i]     = 225 - colors[i];     // red
        colors[i+1] = 225 - colors[i+1]; // green
        colors[i+2] = 225 - colors[i+2]; // blue
        colors[i+3] = 255;   //alpha
    }
    ctx.putImageData(imageData, 220, 0);  //从(220, 0)开始绘制改变过的颜色
}
function toGray() {
    for (var i = 0; i < colors.length; i += 4) {
        var avg = (colors[i] + colors[i+1] + colors[i+2]) / 3;  
        colors[i] = avg; // red
        colors[i+1] = avg; // green
        colors[i+2] = avg; // blue
        colors[i+3] = 255;   //alpha
    }
    ctx.putImageData(imageData, 440, 0); //从(440, 0)开始绘制改变过的颜色
}
invert();   //反转色
toGray();   //变灰色

制图一条直线

在HTML中 <canvas id=”canvas”> </canvas> 创建canvas标签。

在JavaScript中 

var canvas = document.getElementById(“canvas”) //得到canvas一个变量

var context = canvas.getContext(“2d”)
//获得canvas的一个2d的绘图上下文环境。

//使用context进行绘图。canvas绘图的有着接口都是选用context的那么些上下文环境提供。

眼下只举行2d绘图,3D是一点一滴不一致的。

澳门葡京 7

context.moveTo(100,100)是笔尖放到那几个地点,然后context.lineTo(700,700),将要画到这一个地点,不过此地注意,只是一个情状,而context.stroke()才是画出来。

澳门葡京 8

先是成立一个canvas标签,也像其他标签一样,能够设置相关的样式。然后在js中,获取那些canvas,设置宽高,画线。

澳门葡京 9

澳门葡京 10

canvas是基于状态的绘图,所以都是先安装好状态,然后绘制。那么还有何样情状吧?那里有线的涨幅,linewidth和strokeStyle。宽度和线条的样式。那里根本是颜色。也就是说,canvas是基于线条的事态绘制,不是依据对象。大家不是先创建一个canvas的目的,然后设置它的次第属性。对总体安装情状,然后绘制。

澳门葡京 11

如何画折线?再来一个lineTo

澳门葡京 12

同一画一个多头形,一个moveTo,三个lineTo,画一个箭头。

澳门葡京 13

一个moveTo,三回起笔。

如若要绘制三条分歧颜色的折线怎么办呢?分析上边代码对不对?

澳门葡京 14

那是有难题的。因为canvas是场所加绘制。所以上面的动静会覆盖上边的气象。所以效果是下边:

澳门葡京 15

首先段绘制没难点,不过第二段绘制的时候,context.strokeStyle=“green”
覆盖了地方的水彩。同样第两遍,会将方面装有的线又绘制了五回,将拥有情形完结几遍绘制。为粉色。

引出:context.beginPath(),表明从先天伊始要开展一段全新的绘图。当使用beginPath之后,再指定新的门路,再调用绘制的函数,比如stroke(),将绘制从context.beginPath()到context.stroke()之间的意况来开展具体的绘图。

澳门葡京 16

各类beginPath都是一个从新先导绘制。

澳门葡京 17

瞩目context.lineWidth=10,一直在最前面,在context.beginPath()之后,倘诺一个属性从来尚未遮盖的话,将一向保持该意况。而strokeStyle一向被遮盖,所以将用被掩盖的属性值。一定要不一致哪些性质被覆盖,什么性质一向保持着。

率先个beginPath可以简不难单。

beginPath开端一个崭新的路径,moveTo从某点初始,lineTo画到这些点。当使用beginPath之后,首个moveTo可以换成lineTo,因为上一个坐标点被beginPath清空了。

澳门葡京 18

制图封闭的图像,只要第四位相连就好了

澳门葡京 19

澳门葡京 20

但是有一个小缺陷,就是缝合处。因为线段相比宽,如若相比较窄,一个像素,就不会有这些标题。

更好的查封的法子,就是beginPath喝closePath成对出现,那么画出来的形态就是查封的。

澳门葡京 21

澳门葡京 22

澳门葡京 23

澳门葡京 24

澳门葡京 25

现在就宏观封闭了。关于closePath还有一些,即便最终一个lineTo没有写,照旧是全自动用直线将末了一个点总是第二个点。

澳门葡京 26

澳门葡京 27

一个填写的颜料,加一个拓展填写。上面具体事例:

澳门葡京 28

澳门葡京 29

里头有了填充色,而且线条有10个像素,但是其中的5个像素被填充了,要化解这一个难点,肯定是先填充,后对线条描边。

澳门葡京 30

澳门葡京 31

没难点了啊

fillstyle和strokeStyle都是对事态的概念。context基于状态的绘图的,所以能够把所有的情景放在一起,再把具有的绘图放在一块儿,那样也是不影响结果的。如下

context.lineWidth = 10 

context.fillStyle = “yellow”

context.strokeStyle = “#058”

//以上都是意况

context.fill()

contex.stroke()

//举办绘图

澳门葡京 32

流传参数,cxt上下文环境,就是传播的context,x,y绘制的发端位置。矩形的宽和高,边框的宽和颜色,填充色。

澳门葡京 33

澳门葡京 34

制图中矩形相比多,所以有特其他矩形绘制函数,rect(x,y,width,height),绘制的源点,宽和高。

澳门葡京 35

那四个结果是相同的。还有更有益的三个:

澳门葡京 36

fillRect使用当前的fillStyle,而strokeRect使用strokeStyle绘制当前的矩形边框。和rect()不一致是,rect()状态,还亟需绘制一下,不过fillRect和strokeRect直接绘制出来了。

澳门葡京 37

看那八个有分其他。

澳门葡京 38

后绘制的图纸会遮掩前边绘制的图纸。

澳门葡京 39

支撑css援助的体裁

澳门葡京 40

澳门葡京 41

澳门葡京 42

澳门葡京 43

澳门葡京 44

澳门葡京 45

* 用 moveTo方法移动到起源;

特性优化

  • 坐标点尽量用整数

浏览器为了达到抗锯齿的功能会做额外的演算。为了防止那种状态,请保管使用canvas的绘图函数时,尽量用Math.floor()函数对具备的坐标点取整。比如:

ctx.drawImage(myImage, 0.3, 0.5);  //不提倡这样写,应该像下面这样处理
ctx.drawImage(myImage, Math.floor(0.3), Math.floor(0.5));
  • 利用七个画布绘制复杂气象

诸如做一个戏耍,有多少个规模:背景层(简单变化)、游戏层(时刻扭转)。这些时候,我们就足以创制三个画布,一个尤其用来绘制不变的背景(少量绘制),另一个用来绘制游戏动态部分(多量制图),似乎这么:

<canvas id="background-can" width="480" height="320"></canvas>
<canvas id="game-can" width="480" height="320"></canvas>
  • 用CSS设置静态大图

借使有一层是永远不变的,比如一张静态的背景图,最好使用div+css的方法去替代ctx.drawimage(),这么做可以避免在每一帧在画布上绘制大图。简单讲,dom渲染肯定比canvas的操作质量更高。

  • 尽量少操作canvas的缩放

设若要对一个画布举行缩放,要是可以的话,尽量选用CSS3的transform来落到实处。不言而喻,记住一个规范,能用html+div完毕的玩命不要js对canvas进行操作。

  • more
  1. 将画布的函数调用集合到共同(例如,画一条折线,而不用画多条分开的直线)
  2. 选取区其余办法去破除画布(clearRect()、fillRect()、调整canvas大小)
  3. 尽可能防止 shadowBlur特性
  4. 有动画,请使用window.requestAnimationFrame()
    而非window.setInterval()

线条的习性

linewidth就是线条属性的一种

线条的帽子:lineCap

设置线条两端的情形,默许是butt,还能是round和square,圆头和方头。

现实如下:

澳门葡京 46

澳门葡京 47

澳门葡京 48

round是一个圆形的头,square是方形的头。butt是绝非的。注意lineCap只好用于线段的上马三保结尾处,不可能用来线段的连接处。

澳门葡京 49

在上马的地点,是圆头,都是在接连的地点,是尖角。

澳门葡京 50

地点没有beginPath和closePath时候,最终的接连是不缝合的。

澳门葡京 51

加上context.linCap = ”square”时候

澳门葡京 52

是因为square是方形的头,所以会自动补上。然而闭合的图样,如故提出利用beginPath和closePath。

* 用 arc和 lineTo等措施绘制子路径;

画一个五角星

澳门葡京 53

澳门葡京 54

大圆上五个点,小圆上八个点,可以求出右侧大圆上和小圆的点,下一个点离开72度,所以可以通过一个循环,遍历四个点。

澳门葡京 55

cos和sin函数里先角度转弧度。400是将圆心给移动一下。

为了能复用这么些五角星,给它有些变量:r小圆半径,R大圆半径,x,y圆心偏移量。

澳门葡京 56

调用一下drawStar(context,150,300,400,400)就足以了。

再改正一下,增添一个rot,旋转的角度。

澳门葡京 57

转30度随后的指南

澳门葡京 58

线条的链接:lineJoin和miterLimit

lineJoin线条和线条相交的时候,所展现的景色,默许miter尖角,bevel谢姐,round圆角形式。

尖角正如:

澳门葡京 59

context.lineJoin=bevel 斜接是底下这一个样子:

澳门葡京 60

线条顶端不会成一个角。round是底下样子

澳门葡京 61

澳门葡京 62

看一下miterLimit的意义,默认是10个像素。唯有lineJoin为miter的时候会有其一范围,倘诺超miterLimit过10个像素,就会把lineJoin变成bevel格局。如下:

澳门葡京 63

lineJoin为miter的时候,应该是尖角,然而把内圆改小一些,让尖角更尖。实际如下,因为当先了10像素。

澳门葡京 64

可是把miterLimit改成20自此,就可以正常突显了

澳门葡京 65

澳门葡京 66

澳门葡京 67

澳门葡京 68

=

* 调用 closePath方法(可选)

图表变换

澳门葡京 69

改建画一个五角星的函数,设置填充色和边缘色。

后来在onload函数里面绘制一个粉红色背景,

澳门葡京 70

填充矩形背景大小与canvas一样。填充色为粉色。

澳门葡京 71

写一个循环往复,画200个随机的个别

澳门葡京 72

random为随机生成0-1,然后半径为10-20,小圆半径为大圆的一半。x,y的职分在canvas里面随机,旋转角度a为0-360里随机。每一回刷新成效分裂等。八个优化:有些星星在外头,其它有些星星叠在共同。

澳门葡京 73

地点的drawStar在职能上曾经能完全满足功用了。不过承载作用太多。比如下次想画一个四角星,甚至小圆点,改起来就比较劳苦了。为了缓解这几个难题,

澳门葡京 74

那是一个绘制五角星的函数,在0,0地方,半径为1,同时没有别的偏移,没有其余旋转的五角星。把那样的五角星称为标准五角星。

澳门葡京 75

在drawStar中,先绘制一个正规的五角星,然后再位移,改大小,旋转角度。比如之后要绘制4角星,八角形,只必要变更starPath就好了。同时那里的starPath也足以看作参数进行传递。图形学里,都是那种绘制,先绘制基本的图像,再拓展旋转,改变大小等图形变换。

澳门葡京 76

最常用的三种图形变换。

澳门葡京 77

translate把基坐标的(0,0)点放到了(100,100),然后绘制。效果如图:

澳门葡京 78

不过有一个小陷阱:

澳门葡京 79

澳门葡京 80

三回之后,第三个矩形的岗位,并不是300,300.而是400,400.因为基坐标的职责暴发五回变动。图形变换函数是外加的。为了防止这么些陷阱,可以方向操作一下:

澳门葡京 81

澳门葡京 82

只是逆袭太费事,canvas使用save和restore,用来存储状态,再次来到状态。

澳门葡京 83

那多个成对出现,有限支撑canvas图形绘制状态的正确。先稳住一下starPath中点滴的高低。

澳门葡京 84

首位先有限支撑和苏醒状态。对星星translate改变地点,然后旋转角度,绘制星星,填充色,边缘色,线宽,线交合处,填充,描边。达成后如下:

澳门葡京 85

下边星星大小是同一的,下边看一下行使scale暴发什么样难点,如下演示程序:

澳门葡京 86

如上画三个正方形,位置都是从50,50始发画,大小都是200,200,不过实际效果如下:

澳门葡京 87

岂但尺寸改变了,左上角的坐标也展开了操作,线条的小幅也改成了。scale是有副作用的,比如线条大小,左上角的坐标,这几个是要留意的。

澳门葡京 88

制图大小随机的星星的时候,只可以是割舍边框的绘图了,然后一个转移大小scale。

程序运行的功用如下:

澳门葡京 89

注意缩放的副功用。可能会屏弃一些东西的绘图,或者用我们自己的形式绘制。

澳门葡京 90

深入明白图形变换:

澳门葡京 91

澳门葡京 92

那般一个函数可以取代八个。

澳门葡京 93

澳门葡京 94

此地把水平方向缩放改成2,垂直方向改成1.5。

澳门葡京 95

澳门葡京 96

依旧有从前的两个负效果,地方和边框都更改了、

澳门葡京 97

澳门葡京 98

在档次和垂直方向倾斜0.2的效应。

澳门葡京 99

澳门葡京 100

历次更换的法力是在上四遍的法力之上的。级联的。可是setTransform可以无视之前的transform的作用。

澳门葡京 101

事先的倾斜都不算了。

澳门葡京 102

澳门葡京 103

澳门葡京 104

* 调用 fill或 stroke方法

填充样式

fillStyle 除了颜色,仍能此外的。线性渐变色和镜像渐变色。

澳门葡京 105

多个变量,七个坐标,构成一个线条。渐变线,构成渐变方向和标准。

澳门葡京 106

先是个stop关键色的职位,第一个color关键色是何等颜色。下边例子:

澳门葡京 107

首先个addColorStop 中0.0就是开头地点,为白色,首个addColorStop
中1.0就是为止的职位,为青色。那样就是从左上角0,0到右下角800,800由白至黑的一个渐变色。

澳门葡京 108

几个注意点

1、成立linearGrad之后,addColorStop可以增进无数个的。自己喜爱的顺序添加颜色就好。

澳门葡京 109

渐变线还足以水平和垂直的。

澳门葡京 110

还足以只指定一部分,不是整个画布的。

澳门葡京 111

成立一个渐变到400,400,渐变利落后,其他部分显得的是潜移默化的了断时候的颜料。

还可以够超越画布的最大值。外侧的黑白色不会显得了。

澳门葡京 112

澳门葡京 113

根据上边的渐变色可以转移星空的体裁。创建一个渐变色,从0,0到0,canvas.height,也就是贯通整个屏幕的垂直方向。伸张八个颜色,初步点是灰色,终点是湛蓝。然后把有限变小片段,其余星星的排布在上0.65的区域。如下展现:

澳门葡京 114

放射性的渐变:Radial Gradient

澳门葡京 115

三个同心圆的根基上,6个参数:第二个圆圆点半径,第三个圆圆点半径,整个径向渐变就暴发在那多个圆环之间。

澳门葡京 116

其次个增进颜色。

澳门葡京 117

圆心400,400,半径0,就是一个点,外面圆圆心一样,半径500。添加5种颜色,

澳门葡京 118

内圆半径如若非0,如下:

澳门葡京 119

其一圆白色,外面当先500个像素的半径为黄色。

澳门葡京 120

星空中,径向渐变初叶于底层中点,如下所示:

澳门葡京 121

createPattern

澳门葡京 122

澳门葡京 123

下边分别是no-repeat,repeat-x和repeat-y的体裁

澳门葡京 124

澳门葡京 125

澳门葡京 126

澳门葡京 127

一致canvas画布也可以视作填充格局。

澳门葡京 128

创设了一个backCanvas画布,然后作为填充。

澳门葡京 129

成立画布,设置高宽,画星星。创立好的画布再次回到。

作用如下:

澳门葡京 130

澳门葡京 131

video也可以作为背景填充。

澳门葡京 132

澳门葡京 133

澳门葡京 134

澳门葡京 135

澳门葡京 136

同一,fillstyle也可以行使与strokestyle上边。

=

 

曲线的绘图

澳门葡京 137

澳门葡京 138

6个参数,圆心坐标,半径,开首和竣工的角度,顺时针仍然逆时针。

看这多少个绘制:第三个画10个弧,第一个弧是虚掩的,

澳门葡京 139

其八个个逆时针,

澳门葡京 140

澳门葡京 141

澳门葡京 142

圆角矩形

澳门葡京 143

绘制圆角矩形就足以分为上面8个部分。确认圆心就可以了。

澳门葡京 144

澳门葡京 145

调用drawRoundRect就足以了。

澳门葡京 146

澳门葡京 147

已知的有(x0,y0),根据(x1,y1),(x2,y2)绘制两条直线,然后圆弧与那多少个直线相切,半径为radius。上面具体行使:

澳门葡京 148

制图了一条圆弧和一个条辅助线。

澳门葡京 149

注意,初始点不自然是圆弧的启幕点,其它圆弧的截至点也不必然是终止点,而是切线终止点。起源不自然是切点,甘休于切点,不是终点。

澳门葡京 150

一个制图圆弧的函数,多少个点,一个半径。

假如半径过大,会从起源开头延伸到切点,然后发轫画,画到的也不是终点,而是延长线上的切点。

澳门葡京 151

澳门葡京 152

澳门葡京 153

澳门葡京 154

澳门葡京 155

1.1 用线条绘制路径

贝塞尔曲线 Bezier

澳门葡京 156

以下二次贝塞尔曲线:

澳门葡京 157

网站可以查阅贝塞尔曲线绘制效果。

第四个点是控制点,首个点是终止点。二次曲线不可以绘制波浪线。

以下两回贝塞尔曲线:

澳门葡京 158

澳门葡京 159

有多少个控制点,前多少个是控制点,最终一个是截止点。

其余二次曲线不可以像这么表面增添

澳门葡京 160

澳门葡京 161

澳门葡京 162

澳门葡京 163

澳门葡京 164

澳门葡京 165

澳门葡京 166

context.font 字体的样式,fillStyle填充的水彩,fillText
填充的字体,后边参数是填充字体的岗位。

澳门葡京 167

澳门葡京 168

第多个参数是最大的长度,如果设为400,效果如下

澳门葡京 169

澳门葡京 170

澳门葡京 171

澳门葡京 172

澳门葡京 173

澳门葡京 174

澳门葡京 175

默许是大小和字体,可以设置三个属性。font-style默许normal
,italic斜体字,oblique倾斜字体。

澳门葡京 176

web中恐怕看不出来italic和oblique的界别。

澳门葡京 177

祥和导入的字体,可能斜体和倾斜有分别。

澳门葡京 178

澳门葡京 179

澳门葡京 180

小型大写字母

澳门葡京 181

normal通常指400,同理bold

澳门葡京 182

澳门葡京 183

澳门葡京 184

澳门葡京 185

澳门葡京 186

最简便易行的路子是那几个由直线所构成的。

文本对齐

澳门葡京 187

澳门葡京 188

澳门葡京 189

澳门葡京 190

澳门葡京 191

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>由直线创建路径</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="140">
    Your browser doesn't support the <code>canvas</code> element
</canvas>
<script type="application/javascript">
    var ctx = document.getElementById("canvas").getContext("2d");
    ctx.fillStyle = "yellow";
    ctx.strokeStyle = "black";
    ctx.lineWidth = 4;

    ctx.beginPath();
    ctx.moveTo(10,10);
    ctx.lineTo(110,10);
    ctx.lineTo(110,120);
    ctx.closePath();
    ctx.fill();

    ctx.beginPath();
    ctx.moveTo(150,10);
    ctx.lineTo(200,10);
    ctx.lineTo(200,120);
    ctx.lineTo(190,120);
    ctx.fill();
    ctx.stroke();

    ctx.beginPath();
    ctx.moveTo(250,10);
    ctx.lineTo(250,120);
    ctx.stroke();
</script>
</body>
</html>

此例创制了三条途径,其出示效果如下:

澳门葡京 192

对于第一条路径。此例明确绘制了两条线,然后使用closePath方法,这样canvas就会闭合路径。然后调用了fill方法,用fillStyle属性所定义的体裁填入了那几个图形。

对于首个图形,此例指定了三条子路径,然没有关闭图形。可以见到调用了fill和stroke那多少个主意来给图形填色,并沿着路径绘制了一条线。请留心填充色的绘图方式就行图形已经关闭了那么。canvas元素会假定存在一条从终端到源点的子路径,然后借助它填充图形。比较之下,stroke方法只会顺着已经定义的子路径。

PS:对于第三个图形,在stroke方法以前先调用了fill方法,那会使canvas先用纯色填充图形,然后再顺着路径绘制线条。假如lineWidth属性大于1并且先调用了stroke方法,获得的视觉效果就会有所不一致。更宽的线条会在路子两侧绘制。由此线条的一部分会在调用fill方法时被掩盖,导致线条的幅度变窄。

对于第几个图形,此例只是不难地在两点之间绘制了一条线,因为路径不必然须求包涵多条子路径。我们在绘制线条或未闭合图形时可以接纳lineCap属性来设置线条末端的样式。那么些特性允许的三个值是:butt、round
和square(butt为默许值)。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>设置lineCap属性</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="140">
    Your browser doesn't support the <code>canvas</code> element
</canvas>
<script type="application/javascript">
    var ctx = document.getElementById("canvas").getContext("2d");
    ctx.strokeStyle = "red";
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.moveTo(0,50);
    ctx.lineTo(200,50);
    ctx.stroke();

    ctx.strokeStyle = "black";
    ctx.lineWidth = 40;

    var xpos = 50;
    var styles = ["butt","round","square"];
    for(var i=0;i<styles.length;i++){
        ctx.beginPath();
        ctx.lineCap = styles[i];
        ctx.moveTo(xpos,50);
        ctx.lineTo(xpos,150);
        ctx.stroke();
        xpos += 50;
    }
</script>
</body>
</html>

此例的剧本为每一种体裁都绘制了一条相当粗的线。默许值作为参考线,用它以身作则
round和 square样式在绘制时会超越线条末端。

澳门葡京 193

 

1.2 绘制矩形

rect
方法会给当下路线添加一条矩形的子路径。倘使只须要一个独门的矩阵,那么从前介绍的
fillRect和
strokeRect方法是更贴切的抉择。如果需求给一个更扑朔迷离的图像添加矩形,rect方法就很有用了。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用rect方法绘制矩形</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="140">
    Your browser doesn't support the <code>canvas</code> element
</canvas>
<script type="application/javascript">
    var ctx = document.getElementById("canvas").getContext("2d");

    ctx.fillStyle = "yellow";
    ctx.strokeStyle = "red";
    ctx.lineWidth = 4;

    ctx.beginPath();
    ctx.moveTo(110,10);
    ctx.lineTo(110,100);
    ctx.lineTo(10,10);
    ctx.closePath();

    ctx.rect(110,10,100,90);
    ctx.rect(110,100,130,30);

    ctx.fill();
    ctx.stroke();
</script>
</body>
</html>

选拔rect方法时不需求moveTo方法,因为大家在此方法的前八个参数里曾经指定了矩形的坐标。此例绘制了一对线条,调用closePath方法成立了一个三角形,然后绘制了四个邻接的矩形,此例突显效果如下:

澳门葡京 194

子路径不肯定需求不断才能构成路径。可以绘制几条分离的子路径,它们依旧会被视为同一个图纸的组成部分。修改JavaScript代码如下:

<script type="application/javascript">
    var ctx = document.getElementById("canvas").getContext("2d");
    ctx.fillStyle = "yellow";
    ctx.strokeStyle = "red";
    ctx.lineWidth = 4;

    ctx.beginPath();
    ctx.moveTo(110,10);
    ctx.lineTo(110,100);
    ctx.lineTo(10,10);
    ctx.closePath();

    ctx.rect(120,10,100,90);
    ctx.rect(150,110,130,20);

    ctx.fill();
    ctx.stroke();
</script>

此例里的子路径之间并不随处,但总体结果如故是一条单独的不二法门。当调用
stroke或
fill方法时,它们的效能会利用到独具创制的子路径上,其出示效果如下:

澳门葡京 195

 

2.
制图圆弧

咱俩选取 arc和
arcTo方法在画布上制图圆弧,可是那三种办法绘制圆弧的法门有所不一样。下表介绍了canvas里与圆弧有关的措施:

 澳门葡京 196

 

2.1
使用arcTo方法

下例演示了何等运用arcTo方法:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用arcTo方法</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="140">
    Your browser doesn't support the <code>canvas</code> element
</canvas>
<script type="application/javascript">
    var ctx = document.getElementById("canvas").getContext("2d");
    var point1 = [100,10];
    var point2 = [200,10];
    var point3 = [200,110];
    ctx.fillStyle = "yellow";
    ctx.strokeStyle = "blue";
    ctx.lineWidth = 4;
    ctx.beginPath();
    ctx.moveTo(point1[0],point1[1]);
    ctx.arcTo(point2[0],point2[1],point3[0],point3[1],100);
    ctx.stroke();

    drawPoint(point1[0],point1[1]);
    drawPoint(point2[0],point2[1]);
    drawPoint(point3[0],point3[1]);

    ctx.beginPath();
    ctx.moveTo(point1[0],point1[1]);
    ctx.lineTo(point2[0],point2[1]);
    ctx.lineTo(point3[0],point3[1]);
    ctx.stroke();

    function drawPoint(x,y){
        ctx.lineWidth = 1;
        ctx.strokeStyle = "red";
        ctx.strokeRect(x-2,y-2,4,4);
    }
</script>
</body>
</html>

arcTo方法绘制的半圆形依靠两条线完结。第一条是从上一条子路径的顶峰绘制到前多个点子参数所讲述的点。第二条线是以前四个主意参数所描述的点绘制到第多少个和首个参数所描述的点。然后canvas会绘制从上一条子路径的终端到第四个点时期最短的一条圆弧,其半径由最终一个参数指定。为了让它便宜精晓,此例给画布添加了两条额外的路径来提供部分上下文信息,此例突显效果如下:

澳门葡京 197

能够观察两条灰色的线。此例指定了一个半径,两条线的长短也完全一致,这就表示大家取得一条匀称的曲线,刚好触遭遇上一条子路径的终点和首个与第二个参数所讲述的点。半径和线条长度并不总是有着那样福利的尺码,所以canvas会基于须要调整所绘制的拱形。演示例子如下,此例使用事件监控鼠标运动,在屏幕上的鼠标移动时为不一样的点绘制圆弧:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>响应鼠标绘制移动绘制圆弧</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="140">
    Your browser doesn't support the <code>canvas</code> element
</canvas>
<script type="application/javascript">
    var canvasElement = document.getElementById("canvas");
    var ctx = document.getElementById("canvas").getContext("2d");
    var point1 = [100,10];
    var point2 = [200,10];
    var point3 = [200,110];
    draw();

    canvasElement.onmousemove = function(e){
        if(e.ctrlKey){
            point1 = [e.clientX, e.clientY];
        }else if(e.shiftKey){
            point2 = [e.clientX, e.clientY];
        }else {
            point3 = [e.clientX, e.clientY];
        }
        ctx.clearRect(0,0,500,140);
        draw();
    }

    function draw(){
        ctx.fillStyle = "yellow";
        ctx.strokeStyle = "blue";
        ctx.lineWidth = 4;
        ctx.beginPath();
        ctx.moveTo(point1[0],point1[1]);
        ctx.arcTo(point2[0],point2[1],point3[0],point3[1],50);
        ctx.stroke();

        drawPoint(point1[0],point1[1]);
        drawPoint(point2[0],point2[1]);
        drawPoint(point3[0],point3[1]);

        ctx.beginPath();
        ctx.moveTo(point1[0],point1[1]);
        ctx.lineTo(point2[0],point2[1]);
        ctx.lineTo(point3[0],point3[1]);
        ctx.stroke();
    }
    function drawPoint(x,y){
        ctx.lineWidth = 1;
        ctx.strokeStyle = "red";
        ctx.strokeRect(x-2,y-2,4,4);
    }
</script>
</body>
</html>

根据按键的不比,此例中的脚本会随着鼠标运动不一样的点。

澳门葡京 198

 

2.2 使用arc方法

arc方法运用起来略微简单一些。用前几个点子参数在画布上指定一个点。用首个参数指定圆弧的半径,然后指定圆弧的早先和竣工角度。最后一个参数指定绘制圆弧时是按顺时针如故逆时针方向。示例如下:

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用arc方法</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="140">
    Your browser doesn't support the <code>canvas</code> element
</canvas>
<script type="application/javascript">
    var ctx = document.getElementById("canvas").getContext("2d");
    ctx.fillStyle = "yellow";
    ctx.lineWidth = 3;

    ctx.beginPath();
    ctx.arc(70,70,60,0,Math.PI*2,true);
    ctx.stroke();

    ctx.beginPath();
    ctx.arc(200,70,60,Math.PI/2,Math.PI,true);
    ctx.fill();
    ctx.stroke();

    ctx.beginPath();
    var val = 0;
    for(var i=0;i<4;i++){
        ctx.arc(350,70,60,val,val + Math.PI/4,false);
        val += Math.PI/2;
    }
    ctx.closePath();
    ctx.fill();
    ctx.stroke();
</script>
</body>
</html>

来得效果如下:

澳门葡京 199

如首先个和第四个圆弧所示,我们能够用arc方法绘制完整的圆和常见圆弧。可是,如第多个圆圈所示,大家可以用arc方法创立更为复杂的路径。如果应用arc方法时早已绘制了一条子路径,那么就会有一条线间接从上一条途径的终点绘制到arc方法前五个参数所讲述的坐标上。那条线是非凡添加到大家描述的圆弧上的。此例把那种特点和for循环结合使用,连接四小段围绕着同一些绘制的弧形,从而完毕地点突显的图片。

 

3.
绘制贝塞尔曲线

canvas援救绘制二种贝塞尔曲线:三回和四次。大家拔取一个起源和一个极端,然后添加一个或多少个控制点来形成曲线。canvas贝塞尔曲线的题材在于大家无法博取其余视觉反馈,那就更难以得到我们想要的曲线。下表体现了足以用来绘制曲线的格局:

澳门葡京 200

 

3.1 绘制三次贝塞尔曲线

bezierCurveTo
方法会绘制一条曲线,范围是从上一条子路径的顶峰到第八个与第一个法子参数所指定的点。控制点有四个,它们由前八个参数指定。下边的事例浮现了如何运用那么些措施(并添加了一部分附加路径以便可以更易于理解参数值与曲线之间的涉嫌):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>绘制三次贝塞尔曲线</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="140">
    Your browser doesn't support the <code>canvas</code> element
</canvas>
<script type="application/javascript">
    var canvasElement = document.getElementById("canvas");
    var ctx = canvasElement.getContext("2d");

    var startPoint = [50,100];
    var endPoint = [400,100];
    var cp1 = [250,50];
    var cp2 = [350,50];

    canvasElement.onmousemove = function(e){
        if(e.shiftKey){
            cp1 = [e.clientX, e.clientY];
        }else if(e.ctrlKey){
            cp2 = [e.clientX, e.clientY];
        }
        ctx.clearRect(0,0,500,140);
        draw();
    }

    draw();
    function draw(){
        ctx.lineWidth = 3;
        ctx.strokeStyle = "black";
        ctx.beginPath();
        ctx.moveTo(startPoint[0],startPoint[1]);
        ctx.bezierCurveTo(cp1[0],cp1[1],cp2[0],cp2[1],endPoint[0],endPoint[1]);
        ctx.stroke();

        ctx.lineWidth = 1;
        ctx.strokeStyle = "red";
        var points = [startPoint,endPoint,cp1,cp2];
        for(var i=0;i<points.length;i++){
            drawPoint(points[i]);
        }
        drawLine(startPoint,cp1);
        drawLine(endPoint,cp2);
    }
    function drawPoint(point){
        ctx.beginPath();
        ctx.strokeRect(point[0]-1,point[1]-2,4,4);
    }
    function drawLine(from,to){
        ctx.beginPath();
        ctx.moveTo(from[0],from[1]);
        ctx.lineTo(to[0],to[1]);
        ctx.stroke();
    }

</script>
</body>
</html>

此例的脚本会响应鼠标运动而运动贝塞尔曲线上的控制点。其作用如下:

澳门葡京 201

 

3.2 绘制二次贝塞尔曲线

二次贝塞尔曲线唯有一个控制点,因而  quadraticCurveTo 方法的参数比
bezierCurveTo 方法要少四个。修改下边例子脚本中的draw 函数如下:

    function draw(){
        ctx.lineWidth = 3;
        ctx.strokeStyle = "black";
        ctx.beginPath();
        ctx.moveTo(startPoint[0],startPoint[1]);
        ctx.quadraticCurveTo(cp1[0],cp1[1],cp2[0],cp2[1]);
        ctx.stroke();

        ctx.lineWidth = 1;
        ctx.strokeStyle = "red";
        var points = [startPoint,endPoint,cp1,cp2];
        for(var i=0;i<points.length;i++){
            drawPoint(points[i]);
        }
        drawLine(startPoint,cp1);
        drawLine(endPoint,cp2);
    }

其出示效果如下:

澳门葡京 202

 

4.
创办剪辑区域

面前有介绍可以用stroke 和fill
方法来绘制或填充一条途径。还有另一种艺术得以做到那或多或少。

澳门葡京 203

如若定义了一块剪裁区域,就惟有区域内的门路才会呈现到屏幕上了。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用剪裁区域</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="140">
    Your browser doesn't support the <code>canvas</code> element
</canvas>
<script type="application/javascript">
    var canvasElement = document.getElementById("canvas");
    var ctx = canvasElement.getContext("2d");
    ctx.fillStyle = "yellow";
    ctx.beginPath();
    ctx.rect(0,0,500,140);
    ctx.fill();

    ctx.beginPath();
    ctx.rect(100,20,300,100);
    ctx.clip();

    ctx.fillStyle = "red";
    ctx.beginPath();
    ctx.rect(0,0,500,140);
    ctx.fill();
</script>
</body>
</html>

此例的剧本绘制了一个填满画布的矩形,然后创设了一个较小的剪裁区域并绘制了另一个填满画布的矩形。从下图可以见到,第三个矩形只绘制了剪裁区域之内的一部分。

澳门葡京 204

 

5. 绘制文本

可以在画布上制图文本,但是对那种效用的支撑还很初阶。下表突显了可用的艺术。

澳门葡京 205

俺们能够动用二种绘制状态属性来支配文件绘制的法子:

澳门葡京 206

上面的事例体现了什么填写和描边文本。大家可以用与CSS字体简写属性相同的格式字符串来指定font属性的值:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>在画布上绘制文本</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="140">
    Your browser doesn't support the <code>canvas</code> element
</canvas>
<script type="application/javascript">
    var ctx = document.getElementById("canvas").getContext("2d");
    ctx.fillStyle = "lightgrey";
    ctx.strokeStyle = "black";
    ctx.lineWidth = 3;

    ctx.font = "100px sans-serif";
    ctx.fillText("Hello",10,100);
    ctx.strokeText("Hello",10,100);

    ctx.fillText("Luka",250,100);
    ctx.strokeText("Chao",250,100);
</script>
</body>
</html>

此例效果如下:

澳门葡京 207

 

6.
施用特效和转换

咱俩得以为画布应用许多特效和转换。

6.1 使用阴影

可以用七种绘制状态属性来给在画布上绘制的图样和文书添加阴影。

澳门葡京 208

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>给图形和文本应用阴影</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="140">
    Your browser doesn't support the <code>canvas</code> element
</canvas>
<script type="application/javascript">
    var ctx = document.getElementById("canvas").getContext("2d");
    ctx.fillStyle = "lightgrey";
    ctx.strokeStyle = "red";
    ctx.lineWidth = 3;

    ctx.shadowOffsetX = 5;
    ctx.shadowOffsetY = 5;
    ctx.shadowBlur = 5;
    ctx.shadowColor = "blue";

    ctx.strokeRect(250,20,100,100);
    ctx.beginPath();
    ctx.arc(420,70,50,0,Math.PI,true);
    ctx.stroke();

    ctx.beginPath();
    ctx.arc(420,80,40,0,Math.PI,false);
    ctx.fill();

    ctx.font = "100px sans-serif";
    ctx.fillText("Hello",10,100);
    ctx.strokeText("Hello",10,100);
</script>
</body>
</html>

此例的突显效果如下所示,各样文本图形都利用了影子。所有无论图形时开放、闭合、填充依然描边,都能利用阴影。

澳门葡京 209

 

6.2 使用透明度

可以用三种办法来给大家绘制的文本和图纸设置透明度。第一种是选择rgba函数(不是rgb)指定一个fillStyle
或strokeStyle
值。还可以够使用绘图状态属性globalAlpha,它利用的透明度是全局性的。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用globalAlpha属性</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="140">
    Your browser doesn't support the <code>canvas</code> element
</canvas>
<script type="application/javascript">
    var ctx = document.getElementById("canvas").getContext("2d");
    ctx.fillStyle = "lightgrey";
    ctx.strokeStyle = "black";
    ctx.lineWidth = 3;

    ctx.font = "100px sans-serif";
    ctx.fillText("Hello",10,100);
    ctx.strokeText("Hello",10,100);

    ctx.fillStyle = "red";
    ctx.globalAlpha = 0.5;
    ctx.fillRect(100,10,150,100);
</script>
</body>
</html>

globalAlpha
属性的值能够从0(完全透明)到1(完全不透明,那是默许值)。此例绘制了一些文本,将globalAlpha
属性设为0.5,然后在文字上有些填充了一个矩形,其出示效果如下:

澳门葡京 210

 

6.3 使用合成

可以将透明度与globalCompositeOperation属性结合使用,来支配图形和文件在画布上绘制的艺术。下表介绍了这几个特性允许的值。对于那些特性来说,source
包蕴了在该属性设置后执行的兼具操作,而目的图像是性质设置时画布状态。

澳门葡京 211

globalCompositeOperation
属性的值可以成立出部鲜明明的效益。上面的例证包罗了一个select元素,它里面的选项包涵了富有的合成属性值。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用globalCompositeOperation属性</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<div>
<canvas id="canvas" width="500" height="140">
    Your browser doesn't support the <code>canvas</code> element
</canvas>
</div>
<div>
<label>Composition Value:</label>
<select id="list">
    <option>copy</option>
    <option>destination-atop</option>
    <option>destination-in</option>
    <option>destination-out</option>
    <option>destination-over</option>
    <option>lighter</option>
    <option>source-atop</option>
    <option>source-in</option>
    <option>source-out</option>
    <option>source-over</option>
    <option>xor</option>
</select>
</div>
<script type="application/javascript">
    var ctx = document.getElementById("canvas").getContext("2d");
    ctx.fillStyle = "lightgrey";
    ctx.strokeStyle = "black";
    ctx.lineWidth = 3;

    var compVal = "copy";
    document.getElementById("list").onchange = function(e){
        compVal = e.target.value;
        draw();
    }
    draw();
    function draw(){
        ctx.clearRect(0,0,300,120);
        ctx.globalAlpha = 1.0;
        ctx.font = "100px sans-serif";
        ctx.fillText("Hello",10,100);
        ctx.strokeText("Hello",10,100);
        ctx.globalCompositeOperation = compVal;
        ctx.fillStyle = "red";
        ctx.globalAlpha = 0.5;
        ctx.fillRect(100,10,150,100);
    }
</script>
</body>
</html>

其出示效果如下,有些浏览器解释这么些样式的章程稍有分裂,因而看到的恐怕与图中那是显得的不完全一致。

澳门葡京 212

6.4 使用变换

 大家得以给画布应用变换,它会利用到持续所有的绘图操作上。

澳门葡京 213

这一个措施创建的变换只会利用到后续的绘图操作上(画布上存活的内容保持不变)。下边的例子体现了怎么着行使缩选拔和坐标重映射方法。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用变换</title>
    <style>
        canvas {border: thin solid orange;}
        body > * {float: left;}
    </style>
</head>
<body>
<div>
    <canvas id="canvas" width="500" height="140">
        Your browser doesn't support the <code>canvas</code> element
    </canvas>
</div>
<script type="application/javascript">
    var ctx = document.getElementById("canvas").getContext("2d");
    ctx.fillStyle = "lightgrey";
    ctx.strokeStyle = "black";
    ctx.lineWidth = 3;

    ctx.clearRect(0,0,300,120);
    ctx.globalAlpha = 1.0;
    ctx.font = "100px sans-serif";
    ctx.fillText("Hello",10,100);
    ctx.strokeText("Hello",10,100);

    ctx.scale(1.3,1.3);
    ctx.translate(100,-50);
    ctx.rotate(0.5);

    ctx.fillStyle = "red";
    ctx.globalAlpha = 0.5;
    ctx.fillRect(100,10,150,100);
    ctx.strokeRect(0,0,300,200);
</script>
</body>
</html>

此例填充并描边了有的文件,然后缩放、坐标重映射和旋转了画布,那个操作影响了接下去绘制的贯彻矩形和空心矩形。其出示效果如下:

澳门葡京 214

 

来源:《HTML5高于指南》(《The Definitive Guide to
HTML5》)

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website