小白也能看懂的H5 Canvas

banner

Canvas是常見的前端技術,可是因爲API衆多,使用複雜,且對程序員的數學功底、空間想象能力乃至審美都有必定要求,因此真正擅長canvas的前端並很少,但並不表明你們就學很差canvas。我在此將經常使用的canvas使用場景羅列出來但願能幫助到你們。html

建立canvas

Canvas的建立很簡單,只須要一個<canvas>標籤足以,而內部複雜的實現都交給瀏覽器搞定。前端

html:程序員

<canvas id="canvas"></canvas>

全部的繪製動做都須要在canvas上下文(context)中進行,所以咱們須要先建立一個上下文。web

js:canvas

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

除了2d,上下文還能夠設置爲:webgl, webgl2, bitmaprenderer瀏覽器

設置canvas尺寸

js:網絡

canvas.width = 600;
canvas.height = 600;

若要滿屏顯示能夠:ide

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

繪製圖形

1、矩形(Rect)

一、實心矩形(fillRect

繪製實心矩形最簡單的是用 fillRect(x, y, width, height) 方法,參數中 x, y 表示矩形左上角的座標;widthheight 分別表示矩形的寬、高。使用方法以下:學習

js:字體

// 設置填充顏色
ctx.fillStyle = 'skyblue';
// 繪製實心矩形
ctx.fillRect(20, 20, 150, 100);

效果:

實心矩形

二、空心矩形(strokeRect

與繪製實心矩形相似的是使用 strokeRect(x, y, width, height) 方法繪製空心矩形。參數與 fillText 方法一致。

js:

// 設置線寬
ctx.lineWidth = 5;
// 設置繪製顏色
ctx.strokeStyle = 'chocolate';
// 繪製空心矩形
ctx.strokeRect(20, 20, 150, 100);

效果:

空心矩形

三、清空矩形區域(clearRect

當要重繪canvas中的內容時(好比動畫),咱們須要先使用 clearRect(x, y, width, height) 清空canvas。

js:

ctx.fillStyle = 'skyblue';
ctx.fillRect(20, 20, 150, 100);
// 清除畫布中的矩形區域
ctx.clearRect(25, 25, 140, 90);

效果:

清空矩形區域

2、文字(Text)

一、實心文字(fillText)

繪製文字也是canvas的基本功能,實心文字可使用 fillText(text, x, y [, maxWidth]) 方法,參數中 text 表示繪製的文字;x, y 爲文字起點的座標;maxWidth 爲可選參數,表示文字的最大寬度,若是文字超過該最大寬度那麼瀏覽器將會經過調整字間距、字體或者壓縮文字來適應最大寬度。

js:

// 設置繪製顏色
ctx.fillStyle = 'purple';
// 設置字體
ctx.font = '30px Arial';
// 繪製實心顏色
ctx.fillText('Hello World', 220, 50);

效果:

實心文字

二、空心文字(strokeText)

相似的,空心文字可使用 strokeText(text, x, y [, maxWidth]) 繪製,參數與 fillText 方法一致:

js:

// 設置線寬
ctx.lineWidth = 3;
// 設置文字顏色
ctx.strokeStyle = 'orange';
// 設置字體
ctx.font = '50px Arial';
// 繪製空心文字
ctx.strokeText('Hello World', 180, 50);

效果:

空心文字

3、路徑(Path)

顧名思義,經過Path咱們能夠定義一段段路徑(或直線、或曲線)來組合出咱們想要的圖形。

1. 矩形

使用Path也能夠繪製矩形,和 fillRectstrokeRect同樣的效果,可是多一個步驟。使用 rect(x, y, width, height) 方法能夠向當前路徑添加一個矩形,該方法只會改變路徑但不會直接渲染出矩形,因此還須要執行 fill()stroke() 方法:

js:

ctx.rect(200, 20, 200, 100);
ctx.fillStyle = 'deeppink';
ctx.fill();

效果:

path rect 1

或者,空心矩形:

ctx.rect(200, 20, 200, 100);
ctx.lineWidth = 3;
ctx.strokeStyle = 'deeppink';
ctx.stroke();

效果:

path rect 2

二、三角形

用路徑能夠繪製各類自定義的圖形,好比三角形:

js:

// 開始繪製路徑
ctx.beginPath();
// 移動至起點
ctx.moveTo(200, 20);
// 繪製線段
ctx.lineTo(300, 20);
ctx.lineTo(250, 150);
ctx.lineTo(200, 20);
// 繪製路徑
ctx.stroke();

效果:

三角形1

或者在繪製最後一邊的時候可使用ctx.closePath(),使路徑閉合。

咱們也能夠將閉合的路徑填充顏色,以實現實心三角形的繪製:

js:

ctx.beginPath();
ctx.moveTo(200, 20);
ctx.lineTo(300, 20);
ctx.lineTo(250, 150);
// 閉合路徑
ctx.closePath();
// 設置填充顏色
ctx.fillStyle = 'coral';
// 填充路徑
ctx.fill();

效果:
三角形2

三、弧線

(1)標準圓弧

Canvas中沒有專門繪製圓的方法,而是使用更加通用的方法arc(x, y, radius, startAngle, endAngle [, anticlockwise]) 繪製弧線,參數中 x, y 爲圓心座標;radius 爲圓的半徑; startAngle 爲弧的初始角度;endAngle 爲弧的結束角度;anticlockwise 表示是否以逆時針方向繪製路徑。例如繪製圓,能夠寫成:

js:

ctx.beginPath();
ctx.arc(300, 300, 60, 0, Math.PI * 2, true);
ctx.stroke();

效果:

circle

(2)二次方曲線

Canvas也支持繪製二次方曲線,使用 quadraticCurveTo(cpx, cpy, x, y) 方法,參數爲兩個點的座標,其中 cpx, cpy 爲控制點的座標;x, y 爲結束點的座標。使用方法以下:

js:

ctx.beginPath();
ctx.moveTo(150, 400);
ctx.quadraticCurveTo(300, 0, 450, 400);
ctx.stroke();

效果:

quadratic curve

(3)貝塞爾曲線

相似的,canvas還支持繪製常見的貝塞爾曲線,使用 bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y),參數中 cp1x, cp1y 爲第一控制點的座標;cp2x, cp2y 爲第二控制點的座標;x, y 爲結束點的座標。一個簡單的貝塞爾曲線能夠表示以下:

js:

ctx.beginPath();
ctx.moveTo(100, 400);
ctx.bezierCurveTo(200, 200, 400, 400, 500, 200);
ctx.stroke();

效果:

bezier

4、圖片(Image)

咱們也能夠將圖片繪製到canvas上面,使用 drawImage() 方法。drawImage()方法有三個重載:

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

各參數的含義爲:

image: 被繪製到canvas上面的圖片源,支持多種類型:CSSImageValue, HTMLImageElement, SVGImageElement, HTMLVideoElement, HTMLCanvasElement, ImageBitmap, OffscreenCanvas

dx: 在canvas上水平方向繪製的起點

dy: 在canvas上垂直方向繪製的起點

dWidth: 在canvas上繪製圖片的寬度

dHeight: 在canvas上繪製圖片的高度

sx: 原始圖片上水平方向裁剪的起點

sy: 原始圖片上垂直方向裁剪的起點

sWidth: 原始圖片上水平方向裁剪的寬度

sHeight: 原始圖片上垂直方向裁剪的高度

前兩個重載比較好理解,就是在canvas上繪製出完整的源圖片,而且能夠經過設置寬高控制圖片的縮放。第三個重載即在canvas上繪製出源圖片的一部分,能夠形象表示爲:

drawImage

圖片源以 HTMLImageElement 爲例,在canvas上繪製圖片能夠這麼實現:

html:

<img id="source" style="display: none;" src="https://unsplash.it/500/300?image=1074" alt="source">

js:

const image = document.getElementById('source');
image.addEventListener('load', e => {
  ctx.drawImage(image, 50, 150, 500, 300);
});

效果:

canvas image

5、動畫(Animation)

使用canvas配合 requestAnimationFrame 能夠很方便的實現一些動畫效果,好比實現一個圓從左往右移動的動畫:

js:

/**
 * 定義圓
 */
const circle = {
  x: 30, // 水平方向的座標
  y: 300, // 垂直方向的座標
  size: 30, // 圓的半徑
  dx: 5, // 水平座標的變化值
  dy: 4 // 垂直座標的變化值
}

/**
 * 繪製圓
 */
function drawCirle() {
  ctx.beginPath();
  ctx.arc(circle.x, circle.y, 30, 0, Math.PI * 2);
  ctx.fillStyle = 'purple';
  ctx.fill();
}

/**
 * 更新canvas實現動畫效果
 */
function update() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  drawCirle();
  circle.x += circle.dx;
  requestAnimationFrame(update);
}

update();

效果:

animation1

咱們也能夠給小球加上碰撞檢測,讓它在canvas裏面來回彈:

js:

function update() {
  ...

  if (circle.x + circle.size > canvas.width || circle.x - circle.size < 0) {
    circle.dx *= -1;
  }

  requestAnimationFrame(update);
}

效果:

animation2

Codepen預覽

或者咱們能夠實現用鍵盤控制圓的移動:

js:

/**
 * 定義圓
 */
const circle = {
  x: 300, // 水平方向的座標
  y: 300, // 垂直方向的座標
  size: 30, // 圓的半徑
  dx: 0, // 水平座標的變化值
  dy: 0, // 垂直座標的變化值
  speed: 10 // 移動速度
}

/**
 * 繪製圓
 */
function drawCirle() {
  ctx.beginPath();
  ctx.arc(circle.x, circle.y, 30, 0, Math.PI * 2);
  ctx.fillStyle = 'purple';
  ctx.fill();
}

/**
 * 更新canvas實現動畫效果
 */
function update() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  circle.x += circle.dx;
  circle.y += circle.dy;
  // 邊界碰撞檢測
  const leftMost = circle.size; 
  const rightMost = canvas.width - circle.size; 
  const topMost = circle.size; 
  const bottomMost = canvas.height - circle.size; 
  if (circle.x < leftMost) {
    circle.x = leftMost;
  }
  if (circle.x > rightMost) {
    circle.x = rightMost;
  }
  if (circle.y < topMost) {
    circle.y = topMost;
  }
  if (circle.y > bottomMost) {
    circle.y = bottomMost;
  }
  // 繪製圓
  drawCirle();
  requestAnimationFrame(update);
}

/**
 * 開始移動
 */
function move(e) {
  const { key } = e;
  if (key === 'ArrowUp' || key === 'Up') {
    circle.dy = -circle.speed;
  } else if (key === 'ArrowDown' || key === 'Down') {
    circle.dy = circle.speed;
  } else if (key === 'ArrowLeft' || key === 'Left') {
    circle.dx = -circle.speed;
  } else if (key === 'ArrowRight' || key === 'Right') {
    circle.dx = circle.speed;
  }
}

/**
 * 中止移動
 */
function stop(e) {
  if (
    e.key == 'Right' ||
    e.key == 'ArrowRight' ||
    e.key == 'Left' ||
    e.key == 'ArrowLeft' ||
    e.key == 'Up' ||
    e.key == 'ArrowUp' ||
    e.key == 'Down' ||
    e.key == 'ArrowDown'
  ) {
    circle.dx = 0;
    circle.dy = 0;
  }
}

document.addEventListener('keydown', move);
document.addEventListener('keyup', stop);
update();

效果:

move with keyboard

Codepen 預覽

Canvas庫

因爲canvas很是的強大,可是API較爲複雜,因此業界出現了不少基於canvas的庫,讓你們使用canvas更加簡單,下面列出一些供你們選擇:

  • Fabric.js 開源的canvas庫,支持SVG和canvas互轉
  • EaselJS 能夠輕鬆使用HTML5 Canvas元素。可用於建立遊戲,生成藝術做品以及其餘高度圖形化創做
  • KonvaJS 用於桌面和移動應用程序的HTML5 2d canvas庫
  • PixiJS HTML5建立引擎:使用最快,最靈活的2D WebGL渲染器建立精美的數字內容
  • Paper.js 矢量圖形腳本中的瑞士軍刀 - 使用HTML5 Canvas將Scriptographer移植到JavaScript和瀏覽器
  • P5.js p5.js是一個客戶端JS平臺,它使藝術家,設計師,學生和任何人均可以學習編碼並在網絡上創造性地表達本身
  • Three.js 使用WebGL渲染器建立易於使用,輕巧的3D庫。該庫還提供了Canvas 2D,SVG和CSS3D渲染器
  • D3.js D3.js是一個JavaScript庫,用於根據數據處理文檔。 D3幫助您使用HTML,SVG和CSS使數據栩栩如生

關於canvas就給你們介紹到這裏,但願有朝一日你們都能用canvas畫出心中最美的風景!

相關文章
相關標籤/搜索