Canvas 都坐下,基本操作

MrZss發表於2019-02-26

前言

從最開始小白使用canvas採坑無數,讓自己也積累了些還不錯的想法,這期內容也是給自己做了些canvas api整理,以及需要注意的地方

參考網站

MDN

文章連結

微信H5實現網頁長按儲存圖片及識別二維碼(canvas轉換)

前端學習筆記----canvas實現畫板及定製畫筆(畫筆錯位,撤回,粗細,顏色)

前端學習筆記----多張圖片生成canvas思路

替換內容

在比較老的不支援 canvas 的瀏覽器中(尤其是IE9之前的IE瀏覽器), canvas 會被標籤中的內容替換(可用於提示不相容canvas)

<canvas width="150" height="150">
  該瀏覽器不相容canvas
</canvas>

<canvas width="150" height="150">
  <img src="images/clock.png" width="150" height="150" alt=""/>
</canvas> 
複製程式碼

渲染上下文 getContext('2d')

獲得渲染上下文和它的繪畫功能。比如說用來定義畫筆樣式以及進行繪畫的所有操作。getContext()只有一個引數

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// ctx 即為 id為canvas的標籤的上下文
複製程式碼

畫布柵格(canvas grid)

Canvas 都坐下,基本操作

Canvas 畫布其實就是像一個座標系,使用內建的Api在畫板上進行繪製,通常來說座標上的一個單位相當於canvas的一個畫素, 柵格就像一個座標系,不過是從左上角開始的,你可以更具座標系來進行繪畫等操作

友情提醒:最好不要使用style 以及 class去定義canvas長寬樣式,畫布中的小格會被style等樣式壓縮或拉伸,這樣你畫的東西就會變形了

那怎麼辦呢

<canvas id="canvas" width="200" height="200"></canvas>
// 直接標籤中設定或者使用canvas上下文
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.width = 200
ctx.height = 200
複製程式碼

圖形

繪製矩形

canvas是按照路徑生成圖形,canvas只支援一種原生的圖形繪製:矩形,不給過通過路徑繪畫使得繪製各種圖形變成了可能

fillRect(x, y, width, height)  //繪製一個填充的矩形
strokeRect(x, y, width, height) //繪製一個矩形的邊框
clearRect(x, y, width, height) //清除指定矩形區域,讓清除部分完全透明。

複製程式碼

x與y指定了在canvas畫布上所繪製的矩形的左上角(相對於原點)的座標。width和height設定矩形的尺寸。

  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');
  ctx.fillRect(25, 25, 100, 100);
  ctx.clearRect(45, 45, 60, 60); // 用來挖空上個圖形
  ctx.strokeRect(150, 50, 50, 50);

複製程式碼

Canvas 都坐下,基本操作

繪製路徑

路徑的組合使你能畫出任何你想要繪製的圖形,就像你在紙上畫畫一樣

beginPath()
// 新建一條路徑,生成之後,圖形繪製命令被指向到路徑上生成路徑。
// 相當於你拿起鉛筆準備畫畫了
closePath()
// 閉合路徑之後圖形繪製命令又重新指向到上下文中。
// 不是每次都需要closePath 來結束繪畫 這個介面功能就相當於 你畫出兩筆後形成一個直角,但你想畫出一個封閉的直接三角形使用這個介面,即可把終點和氣墊自動連上
stroke()
// 通過線條來繪製圖形輪廓。
fill()
// 通過填充路徑的內容區域生成實心的圖形。
複製程式碼
closePath()
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);
ctx.lineTo(20,100);
ctx.lineTo(70,100);

ctx.stroke();
複製程式碼

Canvas 都坐下,基本操作

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);
ctx.lineTo(20,100);
ctx.lineTo(70,100);
ctx.closePath();
ctx.stroke();
複製程式碼

Canvas 都坐下,基本操作
Canvas 都坐下,基本操作

moveTo(x,y)

從哪開始下筆

你的鉛筆尖從哪個點按到畫板上

當然也能使用moveTo 繪製不連續的點

lineTo(x,y)

繪製一條從當前位置到指定x以及y位置的直線。

開始點和之前的繪製路徑有關,之前路徑的結束點就是接下來的開始點,等等。。。開始點也可以通過moveTo()函式改變。

圓弧

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

畫一個以(x,y)為圓心的以radius為半徑的圓弧(圓),從startAngle開始到endAngle結束,按照anticlockwise給定的方向(預設為順時針)來生成。

x,y為繪製圓弧所在圓上的圓心座標。radius為半徑。startAngle以及endAngle引數用弧度定義了開始以及結束的弧度。這些都是以x軸為基準。引數anticlockwise`為一個布林值。為true時,是逆時針方向,否則順時針方向。

友情提醒:arc()函式中表示角的單位是弧度。角度與弧度的js表示式: 弧度=(Math.PI/180)/角度

arcTo(x1, y1, x2, y2, radius)

根據給定的控制點和半徑畫一段圓弧,再以直線連線兩個控制點。

矩形

rect(x, y, width, height)

繪製一個左上角座標為(x,y),寬高為width以及height的矩形。

上色

fillStyle = color

設定圖形的填充顏色。

strokeStyle = color

設定圖形輪廓的顏色。

var ctx = document.getElementById('canvas').getContext('2d');
for (var i=0;i<6;i++){
  for (var j=0;j<6;j++){
    ctx.fillStyle = 'rgb(' + Math.floor(255-42.5*i) + ',' + 
                       Math.floor(255-42.5*j) + ',0)';
    ctx.fillRect(j*25,i*25,25,25);
  }
}
複製程式碼

Canvas 都坐下,基本操作
Canvas 都坐下,基本操作

其他線條Api

lineWidth = value
// 設定線條寬度。
lineCap = type
// 設定線條末端樣式。
lineJoin = type
// 設定線條與線條間接合處的樣式。
miterLimit = value
// 限制當兩條線相交時交接處最大長度;所謂交接處長度(斜接長度)是指線條交接處內角頂點到外角頂點的長度。
getLineDash()
// 返回一個包含當前虛線樣式,長度為非負偶數的陣列。
setLineDash(segments)
// 設定當前虛線樣式。
lineDashOffset = value
// 設定虛線樣式的起始偏移量。
複製程式碼
lineWidth = value 線條寬度。
lineCap = type 線條末端樣式。
type == butt,round ,square
複製程式碼

友情提醒:如使用滑鼠繪製路徑是 使用butt會導致 起始結尾 稜角比較多 可以使用 round 達到更好的視覺效果

Canvas 都坐下,基本操作

lineJoin = type 線條與線條間接合處的樣式。
type = round,bevel,miter。預設是miter。
複製程式碼

友情提醒:同上 使用預設值會導致繪畫時稜角比較多 ,可以使用 round 達到更好的視覺效果

Canvas 都坐下,基本操作

虛線

setLineDash 方法和 lineDashOffset 屬性來制定虛線樣式. setLineDash 方法接受一個陣列,來指定線段與間隙的交替;lineDashOffset屬性設定起始偏移量.

var ctx = document.getElementById('canvas').getContext('2d');
var offset = 0;

function draw() {
  ctx.clearRect(0,0, canvas.width, canvas.height);
  ctx.setLineDash([4, 2]);
  ctx.lineDashOffset = -offset;
  ctx.strokeRect(10,10, 100, 100);
}

function march() {
  offset++;
  if (offset > 16) {
    offset = 0;
  }
  draw();
  setTimeout(march, 20);
}

march();
複製程式碼

Canvas 都坐下,基本操作

影象

canvas也可以吧已經有的圖片 繪製在畫板上進行編輯

var img = new Image();   // 建立一個img
img.src = 'xxx.png'; // 設定圖片地址
複製程式碼

友情提醒:如需把圖片通過src繪製至canvas一定一定要使用img.onload 等待img.src載入完畢再執行渲染至canvas,不然可能渲染空白

var img = new Image();   // 建立img物件
img.onload = function(){
  // 執行drawImage語句
}
img.src = 'myImage.png'; // 設定圖片地址
複製程式碼
繪製

drawImage(image, x, y)

Image 為 上面的img物件或者 canvas 物件 xy 是其在目標 canvas畫布 裡的起始座標。

縮放 Scaling

drawImage(image, x, y, width, height)

這個方法多了2個引數:widthheight,這兩個引數用來控制 當向canvas畫入時應該縮放的大小

切片

如果只需要使用一張影象上的部分 就得使用切片

drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

第一個引數和其它的是相同的,其它8個引數最好是參照右邊的圖解,前4個是定義影象源的切片位置和大小,後4個則是定義切片的目標顯示位置和大小。

Canvas 都坐下,基本操作

save() remote()

兩個騷操作 怎麼個意思呢

把配置好的 樣式 一次次放入一個棧中,需要事在從棧中 取出 就像一個迴文一樣”12344321“

Canvas 都坐下,基本操作


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

  ctx.fillRect(0,0,150,150);   // 使用預設設定繪製一個矩形
  ctx.save();                  // 儲存預設狀態

  ctx.fillStyle = '#09F'       // 在原有配置基礎上對顏色做改變
  ctx.fillRect(15,15,120,120); // 使用新的設定繪製一個矩形

  ctx.save();                  // 儲存當前狀態
  ctx.fillStyle = '#FFF'       // 再次改變顏色配置
  ctx.globalAlpha = 0.5;    
  ctx.fillRect(30,30,90,90);   // 使用新的配置繪製一個矩形

  ctx.restore();               // 重新載入之前的顏色狀態
  ctx.fillRect(45,45,60,60);   // 使用上一次的配置繪製一個矩形

  ctx.restore();               // 載入預設顏色配置
  ctx.fillRect(60,60,30,30);   // 使用載入的配置繪製一個矩形
}
複製程式碼
移動translate
translate(x, y)
複製程式碼

translate方法接受兩個引數。x 是左右偏移量,y 是上下偏移量,如右圖所示。

Canvas 都坐下,基本操作

旋轉 Rotating
rotate(angle)
複製程式碼

這個方法只接受一個引數:旋轉的角度(angle),它是順時針方向的,以弧度為單位的值。

Canvas 都坐下,基本操作

縮放 Scaling

scale(x, y)

友情提醒:預設柵格一個單位為一個畫素 通過scale 進行單位級別的縮放 ,每個影象所佔單位不變

scale方法接受兩個引數。x,y 分別是橫軸和縱軸的縮放因子,它們都必須是正值。值比 1.0 小表示縮小,比 1.0 大則表示放大,值為 1.0 時什麼效果都沒有。