• Canvas使用教程——图形绘制 - [XHTML]

    2008-09-25

    原文:http://developer.mozilla.org/en/Canvas_tutorial/Drawing_shapes 

    The grid

    在我们开始绘制图形前,我们先探讨一下canvas中的网格及坐标空间。在前一篇教程中,我们定义了一个150*150的canvas区域,并在该区域绘制了一个图形。在canvas区域中,以左上角为坐标原点(0,0),坐标最小单位为1px。区域内所有元素相对与原点定位。不过在以后的实例中,我们还会向你展示如何重定义坐标原点、旋转坐标甚至是重新定义坐标单位,但是现在,我们还是从默认设置开始学习。

    Drawing shapes

    与SVG语法不同的是,canvas只提供了一个绘制矩形的语法,其他形状的绘制就必须依靠路径功能来绘制了,哈哈,其实我们已经收集了很多多绘制各种复杂多边形的function,拿来就能用喽。

    Rectangles

    首先让我们来看下,目前有三种绘制矩形的语法:

    fillRect(x,y,width,height) : 绘制一个实心的举行
    strokeRect(x,y,width,height) : 绘制一个矩形边框
    clearRect(x,y,width,height) : 绘制一个透明的矩形

    以上三种方法中都有x和y参数,这对参数的值就是相对于canvas原点(左上角)的距离。

    以下代码为之前教程中出现过的draw()函数,我们这次将三种矩形绘制的方法都写进去:

    function draw(){
      var canvas = document.getElementById('tutorial');
      if (canvas.getContext){
        var ctx = canvas.getContext('2d');

    ctx.fillRect(25,25,100,100); ctx.clearRect(45,45,60,60); ctx.strokeRect(50,50,50,50); } }

    绘制的效果见右图,fillRect函数绘制了一个100*100的大矩形,clearRect函数从这个矩形挖掉了一块60*60的矩形并且strokeRect函数又绘制了一个50*50的矩形边框。在以后的教材中我们将看到另外的clearRect方法以及我们如何为矩形填充不同的颜色和绘制不同的边框。

    与接下来我们要讲的path方法不同,以上三个矩形绘制方法执行后都会立即应用到canvas区域内。

    Drawing paths

    用路径来绘制多边形,以下这些方法我们都是需要的:

    beginPath()
    closePath()
    stroke()
    fill()

    第一步,我们使用beginPath方法声明一个路径,路径的绘制需要用到一系列字方法(lines,arcs,ect)共同配合来完成一个多边形,每次我们用到路径来绘制多边形时,我们都需要声明一个beginPath来开始绘制。

    第二步,我们将需要调用一些特定方法来绘制我们需要的路径,我们很快就会了解到。

    第三步,closePath,是一个可选步骤,这个方法将封闭绘制路径的起点,如果该多边形已经被封闭,那么,这个方法将不产生任何作用。

    最后的步骤,是运用stroke或者fill方法,为绘制好的多边形路径填充颜色或者描边。

    注意:如果用fill方法填充一个未封闭的多边形时,该多边形将被自动封闭,无需closePath帮忙了。

    例如,以下代码将会绘制一个简单的三角形:

    ctx.beginPath();
    ctx.moveTo(75,50);
    ctx.lineTo(100,75);
    ctx.lineTo(100,25);
    ctx.fill();

    moveTo

    这是一个非常有用的函数,虽然该函数不会绘制任何东西,但是它是路径描述中的一个重要的功能。

    moveTo函数将传入2个参数,x坐标和y坐标,以该坐标点为一个新的绘制起点。

    当canvas初始化或者beginPath方法执行后,最起始的坐标点默认是(0,0),在绝大多数的应用中,我们会用moveTo方法来定位路径绘制的起点。我们亦可以用此方法绘制一些没有连接的路径,比如右边的这张笑脸图,用红色线条标识出来的就是用moveTo方法来实现的。

    示例

    ctx.beginPath();
    ctx.arc(75,75,50,0,Math.PI*2,true); // Outer circle
    ctx.moveTo(110,75);
    ctx.arc(75,75,35,0,Math.PI,false);   // Mouth (clockwise)
    ctx.moveTo(65,65);
    ctx.arc(60,65,5,0,Math.PI*2,true);  // Left eye
    ctx.moveTo(95,65);
    ctx.arc(90,65,5,0,Math.PI*2,true);  // Right eye
    ctx.stroke();
    

    Lines

    顾名思义,画直线的方法。

    lineTo(x, y)

    该方法带的2个参数为线段终点的坐标,起点坐标则依赖于上一个路径所申明的终点,当然该线段的起点也可以是由moveTo方法所申明的坐标。

    示例:如右边的图片所示,我们绘制了2个三角形,一个做填充,一个做描边。首先用beginPath方法申明一个新的路径绘制,用moveTo方法定义绘制起点。

    你可能会注意到绘制实心和空心的三角形,其语法略有差异,那是因为当一个多边形需要填充时,其会自动封闭路径的始末端。

     

    // Filled triangle
    ctx.beginPath();
    ctx.moveTo(25,25);
    ctx.lineTo(105,25);
    ctx.lineTo(25,105);
    ctx.fill();
    
    // Stroked triangle
    ctx.beginPath();
    ctx.moveTo(125,125);
    ctx.lineTo(125,45);
    ctx.lineTo(45,125);
    ctx.closePath();
    ctx.stroke();
    

    Arcs

    该方法为绘制弧线或者圆形路径时使用,该方法另一个写法为arcTo,不过该写法仅仅用于safari浏览器,而不会兼容采用Gecko为核心的浏览器。

    arc(x, y, radius, startAngle, endAngle, anticlockwise)

    该方法接收N个参数:x和y为该段弧线所对应的原点坐标;radius为半径;startAngle和endAngle则决定了该段弧线的2个端点,起始和结束的角度以坐标系X轴为衡量基准;anticlockwise为一个布尔值参数,当为true时则逆时针方向画狐,反之则顺时针。

    警告:在firefox的某些beta版本中,最后一个参数被定义为clockwise,请确保将你的浏览器版本升级至最终发布版本。

    注意:在本表达式中的Angle是以弧度为单位呈现的,实际运用中,我们经常需要在角度与弧度之间做一个转换,其JS的转换表达式为:var radians = (Math.PI/180)*degrees

     

    示例:

    for (i=0;i<4;i++){
      for(j=0;j<3;j++){
        ctx.beginPath();
        var x              = 25+j*50;               // x coordinate
        var y              = 25+i*50;               // y coordinate
        var radius         = 20;                    // Arc radius
        var startAngle     = 0;                     // Starting point on circle
        var endAngle       = Math.PI+(Math.PI*j)/2; // End point on circle
        var anticlockwise  = i%2==0 ? false : true; // clockwise or anticlockwise
    
        ctx.arc(x,y,radius,startAngle,endAngle, anticlockwise);
    
        if (i>1){
          ctx.fill();
        } else {
          ctx.stroke();
        }
      }
    }

    Bezier and quadratic curves

    如果我们需绘制更加复杂的曲线路径,我们或许该用到贝塞尔或者2次方程曲线。

    quadraticCurveTo(cp1x, cp1y, x, y) // BROKEN in Firefox 1.5 (see work around below)
    bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
    

    两种曲线有何区别?我们可以参看一下右边这张图,2种曲线都有一个起点和终点(blue point),但是贝塞尔曲线仅有一个“control point”(red point),2次曲线则有2个。

    两个方法中的x和y参数都为曲线的终点坐标,cp1x和cp1y为第一control point的坐标,cp2x和cp2y为2次曲线的第二控制点。

    熟练运用2次曲线和贝塞尔曲线进行路径绘制,是一件蛮有挑战性的工作,因为它不像某些矢量绘图软件,比如ADOBE Illustrator等具有直观的视觉反馈,所以这使得我们在绘制一些复杂的曲线时会遇到一点小困难,不过如果你有耐心和时间的话,你肯定能绘制出许多复杂的曲线来。

    二次曲线示例:

    // Quadratric curves example
    ctx.beginPath();
    ctx.moveTo(75,25);
    ctx.quadraticCurveTo(25,25,25,62.5);
    ctx.quadraticCurveTo(25,100,50,100);
    ctx.quadraticCurveTo(50,120,30,125);
    ctx.quadraticCurveTo(60,120,65,100);
    ctx.quadraticCurveTo(125,100,125,62.5);
    ctx.quadraticCurveTo(125,25,75,25);
    ctx.stroke();
    

    贝塞尔曲线示例:

    // Bezier curves example
    ctx.beginPath();
    ctx.moveTo(75,40);
    ctx.bezierCurveTo(75,37,70,25,50,25);
    ctx.bezierCurveTo(20,25,20,62.5,20,62.5);
    ctx.bezierCurveTo(20,80,40,102,75,120);
    ctx.bezierCurveTo(110,102,130,80,130,62.5);
    ctx.bezierCurveTo(130,62.5,130,25,100,25);
    ctx.bezierCurveTo(85,25,75,37,75,40);
    ctx.fill();
    

    收藏到:Del.icio.us




    评论

  • 非常好的教程,谢谢了。