It' 隨時為你提供協助,Canvas2D

阿倫克萊耶斯基
Aaron Krajeski

在著色器、網格和濾鏡的世界中,Canvas2D 可能無法讓你感到興奮。但應該這樣! 30–40% 的網頁具有 <canvas> 元素,98% 的所有畫布都使用 Canvas2D 算繪內容。車內、冰箱和太空都有 Canvas2Ds。

使用者接受此 API 後,就能使用最先進的 2D 繪圖技術。幸好,我們一直致力在 Canvas2D 中導入新功能,以便採用 CSS、簡化人體工學及改善效能。

第 1 部分:與 CSS 整合

CSS 部分在 Canvas2D 中缺少了幾個繪圖指令。新版 API 添加了多項最受要求的功能

圓角

圓角矩形:網際網路的基石、計算、文明的邊緣,

整體來說,圓角矩形的功能極為實用:就像按鈕、即時通訊泡泡、縮圖、對話泡泡等,都是你命名的。在 Canvas2D 中一律可以製作圓角矩形,只是有點混亂:

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

const top = 10;
const left = 10;
const width = 200;
const height = 100;
const radius = 20;

ctx.beginPath();
ctx.moveTo(left + radius, top);
ctx.lineTo(left + width - radius, top);
ctx.arcTo(left + width, top, left + width, top + radius, radius);
ctx.lineTo(left + width, top + height - radius);
ctx.arcTo(left + width, top + height, left + width - radius, top + height, radius);
ctx.lineTo(left + radius, top + height);
ctx.arcTo(left, top + height, left, top + height - radius, radius);
ctx.lineTo(left, top + radius);
ctx.arcTo(left, top, left + radius, top, radius);
ctx.stroke();

以下所有必要步驟,就是一個普通的簡單圓角矩形:

圓角矩形。

使用新的 API 時,您可以使用 roundRect() 方法。

ctx.roundRect(upper, left, width, height, borderRadius);

因此,上述方法可以完全取代為:

ctx.roundRect(10, 10, 200, 100, 20);

ctx.roundRect() 方法也會採用 borderRadius 引數 (最多四個數字) 的陣列。這些弧度會控制圓角矩形的四個角,與 CSS 供應商相同。例如:

ctx.roundRect(10, 10, 200, 100, [15, 50, 30]);

快來觀看示範影片吧

錐形漸層

您已經看過線性漸層:

const gradient = ctx.createLinearGradient(0, 0, 200, 100);
gradient.addColorStop(0, 'blue');
gradient.addColorStop(0.5, 'magenta');
gradient.addColorStop(1, 'white');
ctx.fillStyle = gradient;
ctx.fillRect(10, 10, 200, 100);

線性漸層。

放射漸層:

const radialGradient = ctx.createRadialGradient(150, 75, 10, 150, 75, 70);
radialGradient.addColorStop(0, 'white');
radialGradient.addColorStop(0.5, 'magenta');
radialGradient.addColorStop(1, 'lightblue');

ctx.fillStyle = radialGradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);

放射漸層。

但要如何展現圓錐曲線呢?

const grad = ctx.createConicGradient(0, 100, 100);

grad.addColorStop(0, 'red');
grad.addColorStop(0.25, 'orange');
grad.addColorStop(0.5, 'yellow');
grad.addColorStop(0.75, 'green');
grad.addColorStop(1, 'blue');

ctx.fillStyle = grad;
ctx.fillRect(0, 0, 200, 200);

錐形漸層。

文字修飾符

Canvas2Ds 的文字轉譯功能實在落後了。Chrome 為 Canvas2D 文字轉譯新增了幾項屬性:

這些屬性全都與名稱相同的 CSS 對應項目相符。

第 2 部分:人體工學調整

過去,Canvas2D 的部分技術是可以採用的,但實作方式簡單卻十分複雜。以下為想使用 Canvas2D 的 JavaScript 開發人員改善了下列品質改善項目:

已重設背景資訊

為解釋清除畫布,我編寫了可能的函式繪製回歸模式

draw90sPattern();

三角形和正方形的復古圖案。

太好了!完成這個圖案後,我想要清除整個畫布,然後畫其他東西。 等等,我們如何再次清理無框畫?太好了!當然是 ctx.clearRect()

ctx.clearRect(0, 0, canvas.width, canvas.height);

糟糕...失敗了。太好了!我必須先重設轉換:

ctx.resetTransform();
ctx.clearRect(0, 0, canvas.width, canvas.height);
空白畫布,

太棒了,放眼的空白畫布。現在,讓我們開始繪製一個適當的水平線:

ctx.moveTo(10, 10);
ctx.lineTo(canvas.width, 10);
ctx.stroke();

水平和對角線。

可惡!答錯了!😡? 這裡還有什麼額外補充線?還有,為什麼是粉紅色?好,我們先檢查 StackOverflow

canvas.width = canvas.width;

為什麼這很傻?為什麼這很難?

...這個新的 API 採用簡單、優雅且美觀的創新技術:

ctx.reset();

抱歉,時間這麼久。

篩選器

可擴充向量圖形篩選器的功能與眾不同。如果您是第一次使用 SVG 濾鏡,我極力建議您參閱「The Art Of SVG Filters and Why It Is Awesome」(迅速應用的 SVG 濾鏡),當中展示了圖片的一些絕佳潛力。

Canvas2D 現已支援 SVG 樣式濾鏡!您只需將篩選器傳遞為指向網頁上其他 SVG 篩選器元素的網址:

<svg>
  <defs>
    <filter id="svgFilter">
      <feGaussianBlur in="SourceGraphic" stdDeviation="5" />
      <feConvolveMatrix kernelMatrix="-3 0 0 0 0.5 0 0 0 3" />
      <feColorMatrix type="hueRotate" values="90" />
    </filter>
  </defs>
</svg>
const canvas = document.createElement('canvas');
canvas.width = 500;
canvas.height = 400;
const ctx = canvas.getContext('2d');
document.body.appendChild(canvas);

ctx.filter = "url('#svgFilter')";
draw90sPattern(ctx);

這會破壞我們的模式:

套用模糊效果的復古圖案。

但是,如果您想在 JavaScript 中執行上述操作,但不對字串感到雜亂,該怎麼辦? 推出新的 API 後,這一切都能實現。

ctx.filter = new CanvasFilter([
  { filter: 'gaussianBlur', stdDeviation: 5 },
  {
    filter: 'convolveMatrix',
    kernelMatrix: [
      [-3, 0, 0],
      [0, 0.5, 0],
      [0, 0, 3],
    ],
  },
  { filter: 'colorMatrix', type: 'hueRotate', values: 90 },
]);

就這麼簡單!歡迎試用並試用這裡提供的參數。

第 3 部分:提升效能

透過新的 Canvas2D API,我們也希望盡可能提升效能。我們新增了幾項功能,讓開發人員可更精細地控管網站,並提供最流暢的影格速率:

會經常閱讀

使用 getImageData() 從畫布讀取像素資料。這可能會費時許久。新的 API 可讓您明確將畫布標示為可供閱讀 (例如產生生成式效果)。這可讓您直接執行最佳化作業,並加快畫布快速進行各種用途。這項功能在 Firefox 中已推出一段時間,因此我們終於將這項功能納入畫布規格中。

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true });

結構定義損失

讓我們再次開心一下!如果用戶端耗盡了 GPU 記憶體或其他災難復原,現在您可以收到回呼,並視需要重新繪製:

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

canvas.addEventListener('contextlost', onContextLost);
canvas.addEventListener('contextrestored', redraw);

如要進一步瞭解畫布結構定義和損失,WHATWG 在維基百科上提供了詳盡的說明

結語

無論您是 Canvas2D 新手、已使用多年,或已經不再使用 Canvas2D,都可以透過我提供的功能為畫布換上新面貌。這種 API 更是一展長才,

特別銘謝

主頁橫幅由 Sandie Clarke 列於 Unsplash 上。