canvas的使用

canvas

簡介

  • canvas最先由Apple引入WebKit,用於Mac OS X 的Dashboard,後來又在Safari和Google Chrome中實現
  • 基於gecko 1.8瀏覽器,好比Firefox 1.5,一樣支持這個元素
  • canvas元素是WhatWG Web application 1.0的一部分,也包含於HTML5
  • H5的canvas元素使用JavaScript在網頁上繪製圖像,默認大小是300*150,能夠自主設置寬高,不建議設置在style樣式中
  • 瀏覽器解析的時候是圖片,能夠控制每一像素
  • canvas不是塊級元素,因此居中的時候須要用display轉化一下
  • canvas擁有多種繪製路徑、矩形、圓形、字符以及添加圖像的方法

繪製步驟

  • 先獲取元素,以後獲取工具,再設置起始位置,以後繪製路徑,最後描邊
  • 描邊過程能夠設置線條顏色
  • 再次繪製的時候會使用以前的樣式,後面的樣式覆蓋前面的web

    ...
      <style>
        canvas{
          border: 1px solid #ccc;
          /*不建議在這裏設置寬高*/
          /*width: 600px;
          height: 300px;*/
        }
      </style>
      ...
      <body>
      <canvas height="300" width="600"></canvas>
      <script>
        //獲取canvas元素
        var canvas=document.querySelector('canvas');
        //獲取繪製環境(工具)
        var ctx=canvas.getContext('2d');
        //設置起始繪圖的位置
        ctx.moveTo(100,100);
        //繪製路徑
        ctx.lineTo(200,100);
        //描邊
        ctx.stroke();
      </script>
      </body>

繪製

基本繪製

  • 線默認是1px,黑色。canvas由像素點組成,以座標的中心繪製。若是是1px的線條,會被座標中心分紅兩部分,每部分0.5px,瀏覽器沒法顯示0.5px,因此顯示成淺色的粗線條。
  • 若是線條的寬度是偶數的,就不會有這種狀況。不過這種效果通常能夠忽略。
  • beginPath表示從新繪製一條線,後面沒有設置的樣式會沿襲前邊線條的樣式
  • 手動閉合,會產生缺口效果
  • 自動閉合closePath
  • 填充fill
  • 無論是手動閉合仍是自動閉合,或者是不封閉,都不會影響填充效果
  • 兩端樣式用lineCap屬性設置,默認是butt,還有round和square值,設置成後兩種的時候,線條會比默認稍長
  • 設置moveTo和lineTo,造成拐點,默認樣式是miter,還有round和bevel值
  • 漸變能夠當作,線條中的每一個像素分別設置顏色。那麼漸變效果用遍歷線條中的每一個像素就能夠實現
  • 遍歷一次,線條的起點moveTo和lineTo就會發生改變

線條

/*1.獲取canvas元素*/
var canvas = document.querySelector('canvas');
/*2.獲取繪製環境  (獲取繪製工具)*/
/*content內容  context 上下文 */
var ctx = canvas.getContext('2d');
/*3.設置起始繪圖的位置*/
ctx.moveTo(100,100);
/*6.設置寬度*/
ctx.lineWidth = 10;
/*4.繪製路徑 */
ctx.lineTo(200,100);
/*7. 設置描邊的顏色*/
ctx.strokeStyle = 'red';
/*5.描邊*/
ctx.stroke();

平行線

/*1.獲取canvas元素*/
var canvas = document.querySelector('canvas');
/*2.獲取繪製環境  (獲取繪製工具)*/
/*content內容  context 上下文 */
var ctx = canvas.getContext('2d');
/*3.設置起始繪圖的位置*/
ctx.moveTo(100,100);
/*6.設置寬度*/
ctx.lineWidth = 10;
/*4.繪製路徑 */
ctx.lineTo(200,100);
/*7. 設置描邊的顏色*/
ctx.strokeStyle = 'red';
/*5.描邊*/
ctx.stroke();
/*綠色*/
/*再次繪製的時候     會使用以前設置的樣式   設置的樣式最後的會生效*/
/*開啓新路徑*/
ctx.beginPath();
ctx.moveTo(100,200);
ctx.lineTo(200,200);
ctx.strokeStyle = 'green';
ctx.stroke();

三角形

var canvas  = document.querySelector('canvas');
/*獲取繪圖工具*/
var ctx = canvas.getContext('2d'); /*3d目前還不支持*//*webgl*/
/*移動畫筆*/
ctx.moveTo(100,100);
ctx.lineTo(200,100);
ctx.lineTo(200,200);
//ctx.lineWidth = 10;
/*自動閉合*/
ctx.closePath();
//ctx.stroke();
//ctx.strokeStyle = 'red';
//ctx.stroke();
/*填充*/
//ctx.fillStyle = 'red';
ctx.fill();

鏤空矩形

var canvas  = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
/*1.獲取畫布的寬度和高度*/
//var width = canvas.width;
var width = ctx.canvas.width;
var height = ctx.canvas.height;
/*2.假設大容器  200*200*/
/*3.假設小容器  100*100*/
/*4. 計算起始位置*/
var x = width/2 - 100;
var y = height/2 -100;
ctx.moveTo(x,y);
ctx.lineTo(x+200,y);
ctx.lineTo(x+200,y+200);
ctx.lineTo(x,y+200);
ctx.lineTo(x,y);
/*第二個方形的方向須要是逆方向*/
var x1 = width/2 - 50;
var y1 = height/2 -50;
ctx.moveTo(x1,y1);
ctx.lineTo(x1,y1+100);
ctx.lineTo(x1+100,y1+100);
ctx.lineTo(x1+100,y1);
ctx.lineTo(x1,y1);
ctx.stroke();
ctx.fill();

線兩端

var canvas  = document.querySelector('canvas');
/*獲取繪圖工具*/
var ctx = canvas.getContext('2d'); /*3d目前還不支持*//*webgl*/

ctx.lineWidth = 10;
ctx.moveTo(100,100);
ctx.lineTo(200,100);
ctx.strokeStyle = 'red';
ctx.lineCap = 'butt';
ctx.stroke();

ctx.beginPath();
ctx.moveTo(100,200);
ctx.lineTo(200,200);
ctx.strokeStyle = 'green';
ctx.lineCap = 'round';
ctx.stroke();

ctx.beginPath();
ctx.moveTo(100,300);
ctx.lineTo(200,300);
ctx.strokeStyle = 'pink';
ctx.lineCap = 'square';
ctx.stroke();

線拐點

var canvas  = document.querySelector('canvas');
/*獲取繪圖工具*/
var ctx = canvas.getContext('2d'); /*3d目前還不支持*//*webgl*/

ctx.lineWidth = 10;
ctx.moveTo(100,100);
ctx.lineTo(150,150);
ctx.lineTo(200,100);
ctx.strokeStyle = 'red';
ctx.lineJoin = 'miter';
ctx.stroke();

ctx.beginPath();
ctx.moveTo(100,200);
ctx.lineTo(150,250);
ctx.lineTo(200,200);
ctx.strokeStyle = 'green';
ctx.lineJoin = 'round';
ctx.stroke();

ctx.beginPath();
ctx.moveTo(100,300);
ctx.lineTo(150,350);
ctx.lineTo(200,300);
ctx.strokeStyle = 'pink';
ctx.lineJoin = 'bevel';
ctx.stroke();

漸變線

var canvas  = document.querySelector('canvas');
/*獲取繪圖工具*/
var ctx = canvas.getContext('2d'); /*3d目前還不支持*//*webgl*/
/*1.從左到右*/
/*2.起始顏色  白色*/
/*3.結束顏色  紅色*/
ctx.lineWidth = 10;
for (var i = 0; i < 255; i++) {
  ctx.beginPath();
  ctx.moveTo(99+i,100);
  ctx.lineTo(100+i,100);
  var g = 255 - i;
  var b = 255 - i;
  ctx.strokeStyle = 'rgb(255,'+g+','+b+')';
  ctx.stroke();
}

虛線

  • 用setLineDash設置虛線
  • 傳入一個數組,數組中的數據依次表示實點空白
  • 若是傳入的是奇數個數據,好比5,10,15,
  • 那麼表示實點五、空白十、實點1五、空白五、實點十、空白15
  • 奇數總會轉換成偶數個數據
  • 另外虛線還有偏移量,負值表示向右偏移canvas

    var canvas  = document.querySelector('canvas');
    /*獲取繪圖工具*/
    var ctx = canvas.getContext('2d'); /*3d目前還不支持*//*webgl*/
    ctx.moveTo(100,100);
    ctx.lineTo(500,100);
    /*繪製虛線的方法*/
    /*傳數組  設置虛線長度的*/
    ctx.setLineDash([5,10]);
    /*offset表示位移*/
    ctx.lineDashOffset=5;
    /*若是是偶數個數設置  */
    /*若是是奇數數個數設置     */
    /*獲取的不重複的一段*/
    console.log(ctx.getLineDash());
    ctx.stroke();

非零繪製原則

  • 從某區域伸出一條線,通過這條線的路徑,順時針方向+1,逆時針方向-1。最終路徑值的和是0,則這個區域就不填充。
  • S1區域,L1伸出來,與一條線交叉,這條線是逆時針,-1
  • S2區域,L2伸出來,與兩條線交叉,兩條線都是逆時針,-1+(-1)=-2
  • S3區域,L3伸出來,與兩條線交叉,一條是逆時針,一條是順時針。-1+(+1)=0
  • 非零填充,爲零不填充

圖片描述

矩形

  • 全部的方法中,前兩個參數表示相對於canvas座標,x和y,後兩個參數表示矩形的大小,長和寬
  • rect沒有本身獨立的路徑,設置完座標和大小時候,還須要手動描邊或填充
  • strokeRect和fillRect都有本身的路徑,能夠直接生成矩形,一個標識描邊生成,另外一個是填充生成
  • clearRect清除繪製內容數組

    var canvas=document.querySelector('canvas');
    var ctx=canvas.getContext('2d');
    ctx.rect(100,100,20,100);
    ctx.strokeRect(200,100,20,100);
    ctx.fillRect(300,100,20,100);
    ctx.clearRect(210,100,20,100);
    ctx.stroke();

漸變方案

  • createLinearGradient前兩個參數表示起點的座標,後兩個參數表示終點座標
  • addColorStop表示顏色的設置,第一個參數表示佔據位置,第二個參數是顏色瀏覽器

    var canvas = document.querySelector('canvas');
    var ctx = canvas.getContext('2d');
    /*漸變的方案*/
    var linearGradient = ctx.createLinearGradient(100,150,300,150);
    /* 0-1  0-100%  */
    linearGradient.addColorStop(0,'red');
    linearGradient.addColorStop(0.5,'blue');
    linearGradient.addColorStop(1,'yellow');
    ctx.fillStyle = linearGradient;
    ctx.fillRect(100,100,200,100);

曲線

var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
/*1.線都是由點構成*/
var yy = 0;
for (var i = 0; i < 600; i++) {
  var x = i;
  /*y會隨着公式去計算*/
  //var y = 2*x;
  var y = Math.pow(x+2,2);
  //var y = Math.sin(x/20)*100 + 300;
  ctx.beginPath();
  ctx.moveTo(x,yy);
  ctx.lineTo(x+1,y);
  yy = y;
  ctx.stroke();
}

圓弧

  • 圓弧繪製arc方法有六個參數
  • 前兩個參數表示圓心的座標,第三個參數表示圓弧的半徑,第四個參數表示開始的弧度,第五個參數表示結束的弧度,第六個參數表示繪製方向,默認值是false順時針
  • 一個弧度的長度等於半徑的長度,一個周長等於2*π個弧度
  • 周長是2Math.PIr,一個角度就是Math.PI/180
  • 順時針轉是正方向,是正值。逆時針轉是負方向是負值緩存

    var canvas=document.querySelector('canvas');
    var ctx=canvas.getContext('2d');
    ctx.arc(100,100,60,0,2*Math.PI,false);
    ctx.stroke();

文本

  • 文本設置,font設置字體樣式和大小
  • strokeText表示字體描邊,fillText表示字體填充,這兩個方法有四個參數,第一個參數表示要表示出來的文本,第二個和第三個參數表示座標(文本的左下角),第四個參數表示文本最大寬度,能夠不設置
  • textAlign表示文本左右方向的對齊方式,有left,right,center,start,end...
  • textBaseline表示文本上下的對齊方式,有top,middle,bottom,alphabetic(默認值)
  • measureText方法獲取文本的寬度
  • 文本的對齊都是相對於座標點來肯定的
  • 若是設定起始點的座標是(100,100)那麼向右對齊的時候,文本會出如今(100,100)的左邊,上下方式的對齊方式同理app

    var canvas=document.querySelector('canvas');
    var ctx=canvas.getContext('2d');
    ctx.font = '微軟雅黑'
    ctx.stroke();
    ctx.fillText('內容內容',100,100,150);

圖片

  • 建立一個存在於內存中的圖片,有下面兩種方式
  • 文檔中建立元素,設定元素的路徑等屬性
  • 使用Img對象new一個圖片
  • 在IE瀏覽器中,圖片加載以後會有緩存,在onload的時候圖片可能已經加載出來了,因此要把獲取圖片的語句放在onload以後
  • canvas中繪製圖片有三種方式工具

    • 第一種,三個參數字體

      • 參數一,圖片對象。參數二,座標x。參數三,座標y。
    • 第二種,五個參數動畫

      • 參數一,圖片對象。參數二,座標x。參數三,座標y。參數四,圖片寬。參數五,圖片高。
    • 第三種,九個參數webgl

      • 參數一,圖片對象。參數二,圖片x軸定位。參數三,圖片y軸定位。參數四,截取圖片寬度。參數五,截取圖片高度。參數六,繪製x座標。參數七,繪製y座標。參數八,繪製圖片寬度。參數九,繪製圖片高度。
      /*img元素也有onload事件*/
      /*document.querySelector('img').onload = function () {
              console.log('加載完成');
          }*/
      /*怎麼動態建立一個圖片元素*/
      /*這個元素在內存裏面*/
      var img = document.createElement('img');
      img.src = 'images/01.jpg';
      img.onload = function () {
        console.log(img);
      }
      /*使用Image對象*/
      var img1 = new Image();
      img1.onload = function () {
        console.log(img1);
      }
      img1.src = 'images/01.jpg';
      /*補充:兼容問題*/
      /*IE onload必須先綁定*/

精靈圖

  • 從一大張精靈圖中截取須要的部分
  • 獲取畫布的寬高,令圖片居中顯示
  • 九個參數中,獲取img對象,在圖片的(40,195)的位置截取圖片,截取圖片的大小是40X65,放在畫布的(startX,startY)的位置,在畫布中顯示大小是40X65

    var canvas = document.querySelector('canvas');
    var ctx = canvas.getContext('2d');
    var img = new Image();
    img.onload = function () {
      var width = ctx.canvas.width;
      var height = ctx.canvas.height;
      var startX = width/2-20;
      var startY = height/2-32.5;
      /*繪製*/
      ctx.drawImage(img,40,195,40,65,startX,startY,40,65);
    }
    img.src = 'images/03.png';

幀動畫

  • 獲取畫布大小,獲取人物大小,獲得繪製的起點
  • 設置索引值初始值爲0,表明行列中的第幾個圖片
  • 繪製圖片,在圖片(0,0)位置截取圖片,截取大小是人物大小,畫布中繪製起點就是以前計算獲得的結果,圖片大小是人物大小。
  • 設置一個定時器,令index自加,若是index加到3,歸零
  • 繪製圖片以前先清除以前的圖片,清除的起點是繪製圖片的起點,清除範圍的大小是人物的大小
  • 繪製新圖片,截取位置的x方向長度是索引和人物寬度的乘積,y方向就是最後一行的座標195,圖片截取大小就是人物大小,開始位置就是繪製起始位置,畫布中圖片顯示大小就是人物大小

    var canvas = document.querySelector('canvas');
    var ctx = canvas.getContext('2d');
    var img = new Image();
    img.onload = function () {
      /*畫布大小*/
      var width = ctx.canvas.width;
      var height = ctx.canvas.height;
      /*人物大小*/
      var perWidth = img.width/4;
      var perHeight = img.height/4;
      /*繪製起點*/
      var startX = width/2-perWidth/2;
      var startY = height/2-perHeight/2;
      /*繪製*/
      /*圖片的索引*/
      var index = 0;
      ctx.drawImage(img,0,0,perWidth,perHeight,startX,startY,perWidth,perHeight);
      setInterval(function () {
        index ++;
        if(index > 3){
          index = 0;
        }
        /*繪製以前清除以前的圖片*/
        ctx.clearRect(startX,startY,perWidth,perHeight);
        ctx.drawImage(img,index*perWidth,195,perWidth,perHeight,
                      startX,startY,perWidth,perHeight);
      },100);
    }
    img.src = 'images/03.png';

轉換座標軸

  • CSS中translate 在移動的是元素
  • Canvas中 translate移動的事座標軸
  • CSS中rotate旋轉繞元素中心轉,座標軸方向發生改變
  • Canvas中 rotate旋轉繞座標軸原點,座標軸方向發生改變
  • Canvas 中scale x軸的縮放 y軸的縮放 並非元素的縮放

保存和恢復

  • 保存和恢復,保存多個系列,先保存的後被拿出,後保存的先被拿出。棧
  • 若是先保存一個紅色寬30,再保存一個綠色寬20,以後恢復的時候,會先恢復

    var canvas = document.querySelector('canvas');
    var ctx = canvas.getContext('2d');
    
    ctx.lineWidth = 30;
    ctx.strokeStyle = 'red';
    ctx.moveTo(100,100);
    ctx.lineTo(300,100);
    ctx.stroke();
    /*保存一系列樣式*/
    /*保存多個系列樣式*/
    /*存儲結構是棧  後進先出*/
    ctx.save();
    
    ctx.beginPath();
    ctx.lineWidth = 20;
    ctx.strokeStyle = 'green';
    ctx.moveTo(100,200);
    ctx.lineTo(300,200);
    ctx.stroke();
    ctx.save();
    
    ctx.beginPath();
    ctx.restore();
    ctx.moveTo(100,300);
    ctx.lineTo(300,300);
    ctx.stroke();
    
    ctx.beginPath();
    ctx.restore();
    ctx.moveTo(100,400);
    ctx.lineTo(300,400);
    ctx.stroke();

實例

刮刮樂

var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');

var img = new Image();
img.onload = function () {
  /*填充方案*/
  var pat = ctx.createPattern(img,'no-repeat');
  /*圖片描邊*/
  ctx.strokeStyle = pat;
  /*設置線的樣式*/
  ctx.lineWidth = 25;
  ctx.lineCap = 'round';
  ctx.lineJoin = 'round';
  var isDown = false;
  ctx.canvas.addEventListener('mousedown',function (e) {
    /*設置起始座標*/
    ctx.moveTo(e.clientX,e.clientY);
    isDown = true;
  })
  ctx.canvas.addEventListener('mousemove',function (e) {
    if(isDown){
      ctx.lineTo(e.clientX,e.clientY);
      ctx.stroke();
    }
  })
  ctx.canvas.addEventListener('mouseup',function () {
    isDown = false;
  })
}
img.src = 'images/05.jpg';

鍵盤控制人物移動

var Per = function () {
  this.ctx = document.querySelector('canvas').getContext('2d');
  this.width = this.ctx.canvas.width;
  this.height = this.ctx.canvas.height;
  this.stepSize = 10;
  this.index = 0;
}
Per.prototype.init = function () {
  var that = this;
  that.loadImage(function (img) {
    that.perWidth = img.width/4;
    that.perHeight = img.height/4;
    that.startX = that.width/2-that.perWidth/2;
    that.startY = that.height/2-that.perHeight/2;
    that.drawPer(img,0,0,0);
    that.bindEvent(img);
  })
}
/*圖片加載*/
Per.prototype.loadImage = function (callback) {
  var img = new Image();
  img.onload = function () {
    /*完成其餘業務*/
    callback && callback(img);
  }
  img.src = 'images/04.png';
}
/*事件綁定*/
Per.prototype.bindEvent = function (img) {
  var that = this;
  /*按鍵編碼 左上右下 37 38 39 40*/
  /* 0 1 2 3*/
  var direction = 0;
  var stepX = 0;
  var stepY = 0;
  document.addEventListener('keydown',function (e) {
    console.log(e.keyCode);
    switch(e.keyCode){
      case 37:
        /*左*/
        stepX --;
        direction = 1;
        break;
      case 38:
        /*上*/
        stepY --;
        direction = 3;
        break;
      case 39:
        /*右*/
        stepX ++;
        direction = 2;
        break;
      case 40:
        /*下*/
        stepY ++;
        direction = 0;
        break;
    }
    that.index ++;
    /*繪製*/
    that.drawPer(img,stepX,stepY,direction);
  })
}
/*繪製人物*/
Per.prototype.drawPer = function (img,stepX,stepY,direction) {
  /*清空*/
  this.ctx.clearRect(0,0,this.width,this.height);
  if(this.index > 3){
    this.index = 0;
  }
  /*繪製*/
  this.ctx.drawImage(img,this.perWidth*this.index,direction*this.perHeight,
                     this.perWidth,this.perHeight,
                     this.startX+(stepX*this.stepSize),this.startY+(stepY*this.stepSize),
                     this.perWidth,this.perHeight);
}
new Per().init();
相關文章
相關標籤/搜索