Canvas使用教程——几何图形绘制(Drawing shapes)

原文: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();

加支付宝好友偷能量挖...


评论(0)网络
阅读(230)喜欢(0)Canvas/VML/SVG