之前学习过canvas的一些使用,也用过canvas绘制过时钟, 但是很久不用,有些遗忘了,这里做一个简单的回顾。

  

  在web页面创建一个canvas画布非常简单,如下即可:

  1. <canvas id = "parabolic" width="" height=""></canvas>

  注意:canvas元素是一个内联元素。

  

  当然我们也可以修改它的style,如下所示:

  1. #parabolic {
  2. display: block;
  3. background: #ccc;
  4. margin: 200px auto;
  5. }

  这样,我们就可以在页面上得到一个灰色的300px的画布了。

  

  由于我们必须在确保使用<canvas>时所有的页面已经完全加载,所以在js中需要添加:

  1. window.addEventListener("load", function() {
  2. // Your code ...
  3. },false);

  

  接下来我们就可以获得这个canvas元素了:

  1. var myCanvas = document.getElementById("parabolic");

  然后,为了可以在canvas上画图,我们就得先获取到2d环境:

  1. var parabolic = myCanvas.getContext("2d");

  ok! 大功告成,一旦获得了2d环境,我们就可以利用canvas的API进行画图了。

  注: canvas常用的API在这里有详细的说明

  比如最简单的 fillStyle用于设置绘制的颜色, fillRect可以绘制矩形。

  1. parabolic.fillStyle = "#0000ff";
  2. parabolic.fillRect(, , , );

  这就会绘制一个颜色是蓝色的在画布中的位置为(20,40)的宽为50,高为100的矩形。如下:

  而如果使用strokeStyle和strokeRect就会画出一个同样大小的矩形,只是外层是边框,没有完全填充:

  在Canvas的API中还有一个rect方法,这个和strokeRect有什么区别呢?  其实并没有区别,知识,我们得用两步来完成,如下:

  1. parabolic.beginPath();
  2. parabolic.strokeStyle = "blue";
  3. parabolic.rect(, , , );
  4. parabolic.stroke();

  效果如下所示:

  

  于是可以总结区别:

  1.   fillStyle是填充的样式,stroke是绘制的样式
  2. fillRect是填充矩形,必须喝fillStyle配合使用; strokeRect是绘制矩形,必须和strokeStyle配合使用。

  

到这里,其实我们就已经可以总结出规律了,基本上就是下面两种方式:

方式一:

  • 先确定样式 (fillStyle)
  • 再填充路径  (fillReact)

方式二

  • 先确定样式 (fillStyle)
  • 在确定路径(react)
  • 最后进行填充 (fill)

  而 clearRect()的作用是清除选择矩形中的像素

  1. parabolic.fillStyle = "#0000ff";
  2. parabolic.fillRect(, , , );
  3. parabolic.clearRect(,,,);

最终的效果如下所示:

 即我们清除了上面一半的矩形,只剩下下面的矩形了。

    

  如果我们想要绘制一条线,使用lineTo就可以了,如下所示:

  1. parabolic.beginPath();
         parabolic.lineWidth = "";
  2. parabolic.strokeStyle = "red";
  3. parabolic.moveTo(, );
  4. parabolic.lineTo(, );
  5. parabolic.stroke();

  首先,要确定line的宽度,否则最后就什么都看不到了,我们这里是在绘制路径,所以要用stroke, 因为无法填充,所以如果使用fill是得不到结果的。

  moveTo是指将起点移动到的位置,而lineTo是你画的这条线要截至的位置, 之前一直在描述这个路径是怎么样的,最后必须要使用stroke()才能将之绘制出并展示出来。  注意:在每次绘制路径前,我们最好使用 beginPath(), 这是一个好的习惯。

  

  根据上图,可判断canvas的原点是在左上方的,向右为x轴正方向,向下为y轴正方向。 

  如果我们希望制作一个封闭的路径,那么使用closePath往往可以达到我们想要的效果:

  1. parabolic.beginPath();
  2. parabolic.lineWidth = "";
  3. parabolic.strokeStyle = "red";
  4. parabolic.moveTo(, );
  5. parabolic.lineTo(, );
  6. parabolic.lineTo(, );
  7. parabolic.closePath();
  8. parabolic.stroke();

  即我们先从(50, 50)绘制到 (70, 100),然后接着到(90, 50),这时如果stroke我们可以得到一个v形,但是如果我们使用了closePath()方法,这个路径就可以自动闭合了,如下:

  显然,这里的基本思路也是 样式 -> 路径 -> 填充 只是调用不同的api而已,其他并没有什么区别。

  哈哈,在canvas中还有一个比较有意思的就是 arc()方法了, 它可以画弧线,接收六个参数,分别是圆心的x、y坐标,半径,起始和终止的弧度,还有一个可选的true/false即顺时针还是逆时针(true是逆时针),如下:

  1. parabolic.beginPath();
  2. parabolic.strokeStyle = "red";
  3. parabolic.arc(, , , , Math.PI, true);
  4. parabolic.stroke();

  

  我们将绘制弧形的函数进行简单的封装,就可以做出下面的小丑的样式了,

  1. window.addEventListener("load", function() {
  2. var myCanvas = document.getElementById("parabolic");
  3. var parabolic = myCanvas.getContext("2d");
  4.  
  5. // 将绘制圆形的函数进行封装,可以减少代码的重复使用
  6. function paintArc(style, color, x, y, r, start, end, bool) {
  7. parabolic.beginPath();
  8. parabolic[style+"Style"] = color;
  9. parabolic.arc(x, y, r, start, end, bool);
  10. parabolic[style]();
  11. }
  12. paintArc("fill", "blue", , , , , Math.PI, false);
  13. paintArc("fill", "blue", , , , , Math.PI, false);
  14. paintArc("fill", "blue", , , , , Math.PI, true);
  15. paintArc("fill", "blue", , , , , Math.PI, true);
  16. paintArc("stroke", "red", , , , , Math.PI, true);
  17. paintArc("stroke", "red", , , , , *Math.PI, true);
  18. paintArc("fill", "green", , , , , *Math.PI, true);
  19. paintArc("stroke", "red", , , , , *Math.PI, true);
  20. paintArc("fill", "green", , , , , *Math.PI, true);
  21. paintArc("fill", "yellow", , , , , *Math.PI, true);
  22. paintArc("fill", "pink", , , , , Math.PI, false );
  23.  
  24. },false);

  最终效果如下所示:

  

  除此之外,我们还可以看到 quadraticCurveTo() 的二次贝塞尔曲线的API,使用起来也不难。

  二次贝塞尔曲线需要两个点,一个是终点,另外一个是控制点,我们从官网上盗图得到:

  这样,我们就可以得到了,如下所示:

  1. parabolic.beginPath();
  2. parabolic.moveTo(, );
  3. parabolic.strokeStyle = "red";
  4. parabolic.quadraticCurveTo(, , , );
  5. parabolic.closePath();
  6. parabolic.stroke();

  效果如下:

  这里封闭是因为我们使用了closePath方法。

  

  三次贝塞尔曲线和二次贝塞尔曲线的区别并不大,只是多了一个控制点,如下所示:

  下面我们使用贝塞尔曲线就可以绘制处nike的标志了,  

  1. window.addEventListener("load", function() {
  2.  
  3. var myCanvas = document.getElementById("parabolic");
  4. var parabolic = myCanvas.getContext("2d");
  5. parabolic.beginPath();
  6. parabolic.moveTo(, );
  7. parabolic.bezierCurveTo(, , , , , );
  8. parabolic.bezierCurveTo( , , , , , );
  9. parabolic.fill();
  10.  
  11. },false);

  最终效果如下所示:

  这个曲线是贝塞尔曲线的方程,博友写过一篇博客,就是讲解了关于二次贝塞尔曲线和三次贝塞尔曲线的。

  

  在API中,我们还可以发现有一个rotate()方法,使用如下:

  1. drawCurve();
  2. function drawCurve() {
  3. parabolic.beginPath();
  4. parabolic.moveTo(, );
  5. parabolic.rotate(*Math.PI/);
  6. parabolic.bezierCurveTo(, , , , , );
  7. parabolic.stroke();
  8. }

  注意:rotate一定要在 绘制之前, 否则是不起效果的, 可以看到我们一般使用  角度*Math.PI/180 的方式进行旋转

  我们还可以使用 rotate的api,如下所示:

  1. drawCurve();
  2. function drawCurve() {
  3. parabolic.beginPath();
  4. parabolic.moveTo(, );
  5. parabolic.scale(0.5, 0.5);
  6. parabolic.bezierCurveTo(, , , , , );
  7. parabolic.stroke();
  8. }

  最终效果如下:

  不难看出,这时候两边是不一样高的,因为这里的缩放并没有对画布进行缩放, 而只是对最终我们要绘制的路径进行了缩放。即把我们输入的值进行了缩放, 而之前的moteTo里的值始终不改变。

  当然,之前说过,原点默认是在左上方的,但是我们可以使用translate(x, y)方法,将目前处于(0,0)的原点移到(x,y),

  我们还可以在canvas画布中添加字体:

  

  1. parabolic.beginPath();
  2. parabolic.font = "25px Arial";
  3. parabolic.fillText("e瞳网", , );

  其中,font可以设置字体的大小,样式,而fillText()方法可以填充字体, 我们还可以使用strokeText()方法来填充。

  最后需要介绍的就是 save()方法restore()方法

  其中,前者可以保存当前环境的状态,而后者可以返回之前保存的状态。

  

  

最后,使用canvas练习了一个小的例子,但是对于计时器目前还没有完全的了解。

  可以肯定的是,计时器被输出时是一个数字, 在相同的环境下, 被调用一次, 计时器的这个数字就会加1, 另外, 计时器setInterval(func, time)中的第二个参数一般情况下我们最好不要设置太高,控制台16ms以上是最好的,因为一般的浏览器刷新率为16ms一次,所以这个速度是比较合适的。

  另外,在下面的这个例子中,我使用了这篇博文介绍的贝塞尔函数的计算用于控制小球的运动轨迹,效果如下:


  

代码在我的github上。

  

  

  

  

  

   

  

  

  

再探canvas(小球实例)的更多相关文章

  1. 【再探backbone 02】集合-Collection

    前言 昨天我们一起学习了backbone的model,我个人对backbone的熟悉程度提高了,但是也发现一个严重的问题!!! 我平时压根没有用到model这块的东西,事实上我只用到了view,所以昨 ...

  2. 再探jQuery

    再探jQuery 前言:在使用jQuery的时候发现一些知识点记得并不牢固,因此希望通过总结知识点加深对jQuery的应用,也希望和各位博友共同分享. jQuery是一个JavaScript库,它极大 ...

  3. [老老实实学WCF] 第五篇 再探通信--ClientBase

    老老实实学WCF 第五篇 再探通信--ClientBase 在上一篇中,我们抛开了服务引用和元数据交换,在客户端中手动添加了元数据代码,并利用通道工厂ChannelFactory<>类创 ...

  4. 再探ASP.NET 5(转载)

    就在最近一段时间,微软又有大动作了,在IDE方面除了给我们发布了Viausl Studio 2013 社区版还发布了全新的Visual Studio 2015 Preview. Visual Stud ...

  5. c++再探string之eager-copy、COW和SSO方案

    在牛客网上看到一题字符串拷贝相关的题目,深入挖掘了下才发现原来C++中string的实现还是有好几种优化方法的. 原始题目是这样的: 关于代码输出正确的结果是()(Linux g++ 环境下编译运行) ...

  6. ViewPager+Fragment再探:和TAB滑动条一起三者结合

    Fragment前篇: <Android Fragment初探:静态Fragment组成Activity> ViewPager前篇: <Android ViewPager初探:让页面 ...

  7. h5 canvas 小球移动

    h5 canvas 小球移动 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  8. Spark Streaming揭秘 Day7 再探Job Scheduler

    Spark Streaming揭秘 Day7 再探Job Scheduler 今天,我们对Job Scheduler再进一步深入一下,对一些更加细节的源码进行分析. Job Scheduler启动 在 ...

  9. 再探java基础——break和continue的用法

    再探java基础——break和continue的用法 break break可用于循环和switch...case...语句中. 用于switch...case中: 执行完满足case条件的内容内后 ...

随机推荐

  1. 设计模式08: Composite 组合模式(结构型模式)

    Composite 组合模式(结构型模式) 对象容器的问题在面向对象系统中,我们常会遇到一类具有“容器”特征的对象——即他们在充当对象的同时,又是其他对象的容器. public interface I ...

  2. Visual Studio 2013 新增功能:“Browser Link”

    今天新装了 Visual Studio 2013, 使用 VS2013 打开一个现有的 WEB 网站, 在调试网站的时候出现在了脚本错误,一个文件名叫 "browserLink", ...

  3. web端访问文件没有权限的问题

    背景 : ftp的PHP项目中的某些文件没有写入的权限..系统报注意错误!!! 原因 : 一般情况下,web端访问网站一般使用的是WWW权限(有限制的权限组)去访问, 但是我们编程开发的时候, 有可能 ...

  4. StackOverflow: 你没见过的七个最好的Java答案

    StackOverflow发展到目前,已经成为了全球开发者的金矿.它能够帮助我们找到在各个领域遇到的问题的最有用的解决方案,同时我们也会从中学习到很多新的东西.这篇文章是在我们审阅了StackOver ...

  5. oracle重新编译所有invalid objects

    点第一个,按住shift键点最后一个,右键recompile就OK了

  6. tcp连接过程中的三次握手和四次挥手

    在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手握手建立连接 @第一次握手: 建立连接是,客户端A发送SYN包到服务器B,并进入SYN_SEND状态,等待B确认. @第二次握手: 服务 ...

  7. bzoj2395 [Balkan 2011]Timeismoney(最小乘积生成树+计算几何)

    题意 每条边有两个权值\(c,t\),请求出一颗生成树,使得\(\sum c\times \sum t\)最小 题解 为什么生成树会和计算几何扯上关系-- 对于每棵树,设\(x=c,y=t\),我们可 ...

  8. CentOS71611部署Django

    web.conf <VirtualHost *:> WSGIScriptAlias / /var/www/datacn/datacn/wsgi.py Alias /static/ /var ...

  9. 跟我一起读postgresql源码(四)——Planer(查询规划模块)(上)

    时间一晃周末就过完了,时间过得太快,不由得让人倍加珍惜.时间真是不够用哈~ 好的不废话,这次我们开始看查询规划模块的源码吧. 查询规划部分的在整个查询处理模块应该是在一个非常重要的地位上,这一步直接决 ...

  10. Unity---动画系统学习(1)---在状态机中简单控制物体运动

    1. 介绍 新建一个GameObject-Cube,在Window下添加Animation(快捷键ctrl+6).会添加用于播放动画的三个东西.物体上的Animator组件.Animator Cont ...