シェーダー、メッシュ、フィルタの世界では、Canvas2D は魅力的ではないかもしれません。しかし、そのはずです。
ウェブページの 30 ~ 40% に <canvas>
要素があり、すべてのキャンバスの 98% が Canvas2D レンダリング コンテキストを使用しています。Canvas2D は、自動車、冷蔵庫、そして(実際には)宇宙空間に存在します。
最新の 2D 描画に関しては、この API は時代遅れです。幸い、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);
テキスト修飾子
Canvas2D のテキスト レンダリング機能は、Chrome では、Canvas2D テキスト レンダリングにいくつかの新しい属性が追加されました。
- ctx.letterSpacing
- ctx.wordSpacing
- ctx.fontVariant
- ctx.fontKerning
- ctx.fontStretch
- ctx.textDecoration
- ctx.textUnderlinePosition
- gsuite.textRendering
これらの属性はすべて、同じ名前の 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 フィルタは、それ自体が世界です。SVG フィルタについて詳しくは、SVG フィルタの芸術とその優れた点をご覧ください。
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 では、可能な限りパフォーマンスを改善することも目指しました。デベロッパーがウェブサイトをよりきめ細かく制御し、可能な限り滑らかなフレームレートを実現できるように、いくつかの機能を追加しました。
頻繁に読み取る
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 を初めて使用する方、長年使用している方、長年使用していない方、Canvas をもう一度見直すことをおすすめします。ずっと存在していた API です。