Canvas2D では常にあなた。

Aaron Krajeski 氏
Aaron Krajeski

多種多様なシェーダー、メッシュ、フィルタに Canvas2D を活用できる機会は少なくありません。ぜひ読んでみてください。 ウェブページの 30 ~ 40% に <canvas> 要素があり、すべてのキャンバスの 98% が Canvas2D レンダリング コンテキストを使用しています。Canvas2D は、自動車、冷蔵庫、宇宙空間(実際には)にあります。

もちろん、この API は最先端の 2D 描画に少し遅れをとっています。Google は、CSS に追いつくとともに、人間工学の効率化、パフォーマンスの向上のために、Canvas2D の新機能の実装に取り組んできました。

パート 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() メソッドは、最大 4 つの数値からなる borderRadius 引数の配列を受け取ります。この半径は、CSS の場合と同じように、丸い長方形の 4 隅を制御します。例:

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 をお読みになることを強くおすすめします。

Canvas2D では、SVG スタイル フィルタがすでに使用可能となっています。必要な操作は、ページ上の別の SVG フィルタ要素を指す URL としてフィルタを渡すことだけです。

<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 では、パフォーマンスも可能な限り改善したいと考えていました。Google は、デベロッパーがウェブサイトをきめ細かく管理し、可能な限り滑らかなフレームレートを実現できるように、いくつかの機能を追加しました。

頻繁に読む

getImageData() を使用して、キャンバスからピクセルデータを読み取ります。非常に遅くなることがあります。新しい API を使用すると、(たとえば生成効果のために)もう一度読み取るためにキャンバスを明示的にマークできます。これにより、内部での処理を最適化し、さまざまなユースケースでキャンバスを高速に保てます。Firefox で以前からあったこの機能は、ようやく canvas の仕様に組み込まれます。

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 の Wiki の詳しい説明をご覧ください。

まとめ

Canvas2D を初めて使用する方、何年も使っていない方も、キャンバスの新デザインをご紹介します。ここが元々あった API Next です

謝辞

Sandie Clarke 氏による Unsplash のヒーロー画像