canvas学习之路--记录(一)

前言:canvas作为html5出现的新标签,以前接触过一些,也写过一些小的demo,但没有实际去在项目中使用过,直到前段时间,我要写一个前端小游戏,由于当时时间匆忙就没使用canvas,整个项目全部是用html标签来充当游戏当中的元素,结构就是在一些特定手机上相当之卡,个人优化过之后,稍有好转,但依旧不满意,无奈项目紧急,只能事权轻重,先行将项目上线,不过只要有时间,还是将canvas搞懂,以后这种全用canvas写为好...下面进入本菜鸡学习canvas之路吧.(此为作者跟着html5与css3权威指南所学记录).

一、绘制矩形

1.首先要取得canvas元素: 可以用document.getElementById等方法取得canvas对象,后面需要调用这个对象提供的方法来进行图形绘制. 

2.取得上下文: 进行图形绘制时,需要用到图形上下文,图形上下文是一个封装了很多绘图功能的对象,需要使用canvas对象的getContext方法来获得图形上下文. 其中将此方法的参数设为'2d';

3.填充与绘制边框: 用canvas绘制图形的时候,有两种方式--填充(fill)与绘制边框(stroke).填充是指填满图形内部,绘制边框是指不填满图形内部,只绘制图形的外框.

4.设定绘图样式: 在进行图形绘制的时候,首先要设定好绘图的样式(style),然后调用有关方法进行图形的绘制.所谓绘图的样式,主要是针对图形的颜色而言的,但是并不限于图形的颜色.

  fillStyle属性--填充的样式,在该属性中填入填充的颜色值

  strokeStyle--图形边框的样式,在该属性中填入边框的颜色值

5.指定线宽: 使用图形上下文对象的lineWidth属性设置图形边框的宽度,在绘制图形的时候,任何直线都可以通过lineWidth属性来指定直线的宽度

6.指定颜色值: 绘图时填充的颜色或边框的颜色分别通过fillStyle属性和strokeStyle属性来指定,颜色值可使用颜色名(如:red),或十六进制颜色值(如:#f00),或rgb、rgba函数来指定颜色

7.绘制矩形: 分别使用fillRect方法与strokeRect方法来填充矩形会绘制矩形边框,这两个方法的定义如下所示

  context.fillRect(x,y,width,height)

  context.strokeRect(x,y,width,height)

  这里的context指的是图形上下文对象,这两个方法使用同样的参数,x是指矩形起点的横坐标,y是指矩形七点的纵坐标,坐标原点为canvas画布的最左上角,width是指矩形的长度,height是指矩形的高度

 绘制图形代码如下:

function draw (obj) {
    var $myCanvas = document.getElementById(obj);  //canvas对象
    if ($myCanvas == null) return false;
    var $ctx = $myCanvas.getContext('2d');   //获取canvas对象图形上下文
    $ctx.fillStyle = '#f00';
    $ctx.fillRect(50,50,100,100);
    $ctx.strokeStyle = '#ff0';
    $ctx.lineWidth = 10;
    $ctx.strokeRect(50,50,100,100);
}

此外,还有一个clearRect方法,该方法将擦除掉矩形区域内的图形,使矩形区域内的图形全部变成透明,如:context.clearRect(x,y,width,height),方法与上面的类似.

二、使用路径

获取到图形上下文之后,执行如下步骤

开始创建路径-->创建图形的路径-->路径创建完成之后,关闭路径-->设定绘制样式,调用绘制方法,绘制路径.

就是先用路径勾勒图形轮廓,然后设置颜色,进行绘制

1.开始创建路径

使用图形上下文对象的beginPath方法,如context.beginPath();

该方法不适用参数,通过调用该方法开始路径的创建(注:每次开始创建时都要调用beginPath函数)

2.创建圆形路径

创建圆形路径时,需要使用图形上下文对象的arc方法. 如:context.arc(x,y,radius,startAngle,endAngle,anticlockwise).

该方法使用六个参数,x为绘制圆形的圆点横坐标,y为绘制圆形的圆点纵坐标,radius为圆形半径,strartAngle为开始角度,endAngle为结束角度,anticlockwise为是否按照顺时针方向进行绘制

arc方法不仅可以用来绘制圆形,也可以用来绘制圆弧,因此必须指定开始角度和结束角度.aniticlockwise参数是一个布尔值,值为true时,按顺时针绘制,值为false时,按逆时针进行绘制.

3.关闭路径

路径创建完成后,使用图形上下文对象的closePath方法将路径关闭.如:context.closePath();

将路径关闭之后,仅仅是路径创建工作完成了,这时还没有真正绘制任何图形.

4.设定绘制样式,进行图形绘制.

如:context.fillStyle = 'rgba(255,0,0,0.25)';   context.fill();

使用创建好的路径绘制图形:  指定绘制样式(fillStyle,strokeStyle)-->使用fill(或stroke)方法进行'填充图形'(或绘制图形边框),因为路径已经决定了图形的大小,所以就不需要在该方法中是哟红参数来指定图形的大小了.

注意:如果在绘制路径的时候,不执行创建路径语句和关闭路径语句,则以前绘制的路径会一直存在,这时,如果再使用fill()或则stroke()时,会重复绘制先前的图形,进行重叠,如果绘制样式中有透明度设置,则最先绘制的图形颜色会最深

function draw (obj) {
    var $myCanvas = document.getElementById(obj);
    if ($myCanvas == null) return false;
    var $ctx = $myCanvas.getContext('2d');
    $ctx.fillStyle = 'rgba(0,0,0,0.3)';
    $ctx.fillRect(0,0,400,300);
    $ctx.strokeStyle = 'rgb(0,0,0)';
    $ctx.lineWidth = 1;
    $ctx.strokeRect(0,0,400,300);
    
    $ctx.beginPath();
    $ctx.arc(0,0,150,0,2*Math.PI,true);
    $ctx.closePath();
    $ctx.fillStyle = 'rgba(255,0,0,0.5)';
    $ctx.fill();
}

三、moveTo与lineTo

绘制直线时,一般会用到moveTo和lineTo两种方法,功能如下:

moveTo

  moveTo方法的作用是将光标移动到指定款坐标点,绘制直线的时候以这个坐标点为起点,如:moveTo(x,y),该方法使用两个参数--x表示指定坐标点的横坐标,y表示指定坐标点的纵坐标

lineTo

  lineTo方法在moveTo方法中指定的直线起点与参数中指定的直线终点之间绘制一条直线,如lineTo(x,y),使用方法和moveTo(x,y)的方法一样,使用该方法之后,光标自动移动到lineTo方法的参数所指定的直线终点

因此,在创建路径时,需要使用moveTo方法将光标移动到指定的直线起点,然后使用lineTo方法在直线起点和直线终点之间创建路径,然后将光标移动到直线终点,在下一次使用lineTo方法的时候,会以当前光标所在坐标点为直线起点,并在下一次用lineTo方法指定的直线终点之间创建路径,它会不断重复这个过程,来完成复杂图形的路径绘制.

如下:

function draw (obj) {
    var $myCanvas = document.getElementById(obj);
    if ($myCanvas == null) return false;
    var $ctx = $myCanvas.getContext('2d');
    $ctx.fillStyle = '#eef';
    $ctx.fillRect(0,0,400,300);
    var n = 0,
        dx = 150,
        dy = 150,
        s = 100;
    $ctx.beginPath();
    $ctx.fillStyle = 'rgb(100,250,100)';
    $ctx.strokeStyle = 'rgb(0,0,100)';
    var x = Math.sin(0),
        y = Math.cos(0),
        dig = Math.PI / 15 * 11;
    for (var i = 0; i < 30; i++) {
        var x = Math.sin(i * dig),
            y = Math.cos(i * dig);
        $ctx.lineTo(dx + x * s, dy + y * s);
    }
    $ctx.closePath();
    $ctx.fill();
    $ctx.stroke();
}

除此之外,还有使用bezierCurveTo绘制曲线(有兴趣可以自己去研究,本人太菜,加上感觉用不上这么高大上的东西,就不做笔记了)
四、绘制渐变图形

1.绘制线性渐变

前面使用的fillStyle方法在填充时不但可以指定填充的颜色,同时,使用该方法也可以用来指定填充的对象.

这里,可以来看一下渐变,首先是最简单的两点之间的线性渐变.

绘制线性渐变时,需要用到LinearGradient对象.使用图形上下文对象的createLinearGradient方法创建该对象.如:context.createLinearGradient(xStart,yStart,xEnd,yEnd);

该方法有四个参数,xStart-->渐变起点的横坐标,yStart-->渐变起点的纵坐标,xEnd-->渐变终点的横坐标,yEnd-->渐变终点的纵坐标.

通过该方法,创建了一个使用两个坐标点的LinearGradient对象,而渐变的颜色则使用addColorStop方法进行设定,该方法的如:context.addColorStop(offset,color);

该方法可以追加渐变的颜色.该方法使用两个参数--offset和color.

offset为所设定的颜色离开渐变起始点的偏移量,改参数的值是一个范围在0到1之间的浮点值,渐变起点的偏移量为0,渐变结束点的偏移量为1.color为绘制时使用的颜色.

例:

function draw (obj) {
    var $myCanvas = document.getElementById(obj);
    if ($myCanvas == null) return false;
    var $ctx = $myCanvas.getContext('2d');
    var g1 = $ctx.createLinearGradient(0,0,0,300);
    g1.addColorStop(0,'#ff0');
    g1.addColorStop(1,'#0ff');
    $ctx.fillStyle = g1;
    $ctx.fillRect(0,0,400,300);
    $ctx.fill();
    var g2 = $ctx.createLinearGradient(0,0,300,0);
    g2.addColorStop(0,'rgba(255,0,0,0.5)');
    g2.addColorStop(1,'rgba(0,0,255,0.5)');
    $ctx.fillStyle = g2;
    for (var i = 1; i <= 10; i++) {
        $ctx.beginPath();
        $ctx.arc(i * 20,i*20,i*10,0,Math.PI*2,true);
        $ctx.closePath();
        $ctx.fill();
    }
}

2.绘制径向渐变

使用图形上下文对象的createRadialGradient方法绘制径向渐变,如:context.createRadialGradient(xStart,yStart,radiusStart,xEnd,yEnd,radiusEnd);

该方法有两个函数:xStart-->渐变开始圆的圆心横坐标,yStart-->渐变开始圆的圆心纵坐标,radiusStart-->渐变开始圆的半径,xEnd-->渐变结束圆的圆心横坐标,yEnd-->渐变结束圆的圆心纵坐标,radiusEnd-->渐变结束圆的半径

在这个方法中,分别指定了两个圆的大小和半径,从第一个圆的圆心处向外进行扩散渐变,一直扩散到第二个圆的外轮廓处.

设定渐变颜色的方法则与线性渐变相同

function draw (obj) {
    var $myCanvas = document.getElementById(obj);
    if ($myCanvas == null) return false;
    var $ctx = $myCanvas.getContext('2d');
    var g1 = $ctx.createRadialGradient(400,0,0,400,0,400);
    g1.addColorStop(0,'#ff0');
    g1.addColorStop(1,'#0ff');
    $ctx.fillStyle = g1;
    $ctx.fillRect(0,0,400,300);
    $ctx.fill();
}

五、绘制变形图形

默认情况下,canvas画布的最左上角对应坐标原点(0,0).如果对这个坐标使用变换处理,就可以实现图形的变形处理了,对坐标的变换处理,有三种方式:平移、扩大、旋转

平移:

  使用图形上下文对象的translate方法移动坐标轴原点,如context.translate(x,y); ----x表示将坐标轴原点向右移动多少个单位,默认情况下为像素,y表示将坐标轴原点向下移动多少单位.

扩大:

  使用图形上下文对象的scale方法将图形放大,如:context.scale(x,y); ----x表示水平方向的放大倍数,y表示垂直方向的放大倍数.(注:当需要将图形缩小的时候,可以将其参数值设置为0-1之间的小数即可)

旋转:

  使用图形上下文对象的rotate方法将图形进行旋转,如:context.rotate(angle); ----angle表示旋转角度,旋转中心是坐标轴的原点,以顺时针方向进行旋转(注:如需逆时针进行旋转,将angle设定为负数即可)

代码示例:

function draw (obj) {
    var $myCanvas = document.getElementById(obj);
    if ($myCanvas == null) return false;
    var $ctx = $myCanvas.getContext('2d');
    $ctx.fillStyle = '#eef';
    $ctx.fillRect(0,0,400,300);
    $ctx.translate(200,50);
    $ctx.fillStyle = 'rgba(255,0,0,0.25)';
    for (var i = 0; i < 50; i++) {
        $ctx.translate(25,25);
        $ctx.scale(0.95,0.95);
        $ctx.rotate(Math.PI/10);
        $ctx.fillRect(0,0,100,50);
    }
}

坐标变换与路径的结合使用:必须先另写一个创建路径的函数,然后再坐标变换的同时调用该函数

代码示例:

function draw (obj) {
    var $myCanvas = document.getElementById(obj);
    if ($myCanvas == null) return false;
    var $ctx = $myCanvas.getContext('2d');
    $ctx.fillStyle = '#eef';
    $ctx.fillRect(0,0,400,300);
    $ctx.translate(200,50);
    for (var i = 0; i < 50; i++) {
        $ctx.translate(25,25);
        $ctx.scale(0.95,0.95);
        $ctx.rotate(Math.PI/10);
        create5Star($ctx);
        $ctx.fill();
    }
}
function create5Star (context) {
    var n = 0,
        dx = 100,
        dy = 0,
        s = 50;
    context.beginPath();
    context.fillStyle = 'rgba(255,0,0,0.5)';
    var x = Math.sin(0),
        y = Math.cos(0),
        dig = Math.PI/5*4;
    for (var i = 0; i < 5; i++) {
        var x = Math.sin(i*dig),
            y = Math.cos(i*dig);
        context.lineTo(dx+x*s,dy+y*s);
    }
    context.closePath();
}

接下来还有矩阵变换,其中首先涉及到变换矩阵,这个矩阵是专门用来实现图形变形的,它与坐标系一起配合使用,以达到变形的目的,当图形上下文被创建完毕时,事实上也创建了一个默认的变换矩阵,如果不对这个变换矩阵进行修改,那么接下来绘制的图形将以画布的最左上角为坐标原点绘制图形,绘制出来的图形也不经过缩放、变形的处理,如果对这个变换矩阵进行修改,那么情况则完全不一样了.

使用图形上下文对象的transform方法修改变换矩阵,如:context.transform(m11,m12,m21,m22,dx,dy);这里面的m11,m12,m21,m22四个参数涉及到矩阵乘法的,这里不过多介绍(实际上是差不多都丢给老师了)

实际上上面提到的translate,scale,rotate可以对transform进行代替.(太难了,有点研究不透了,结束!)

posted @ 2017-07-05 14:54  上山打松鼠  阅读(798)  评论(0编辑  收藏  举报