Gatsbyで構築された私のサイドプロジェクトであるPurple11の場合、SVGフィルターとCanvasAPIを内部で使用する単純なクラウドテクスチャジェネレーターを作成しました。 feTurbulence フィルターのおかげで、SVGフィルター部分を使用すると、クラウドテクスチャ効果自体を簡単に作成できましたが、SVGフィルターの魅力的なトピックは別の記事に残しておきます。 。

生成されたテクスチャをユーザーがJpegファイルとしてマシンにダウンロードできるようにするには、残念ながら、インラインから直接ダウンロード可能なファイルを生成する方法がないため、インラインSVG(フィルターが適用されている)を最初にキャンバスオブジェクトに描画する必要があります。 SVGグラフィック。 明らかに、[でCanvasAPIを使用して直接描画された画像をダウンロードする方法を知っているだけであれば、SVGからCanvasへの部分全体をスキップして問題の本質に直接スキップできます。 X207X]。

Canvas API全般に不慣れで、概要を知りたい場合は、この記事を確認してください。

インラインSVGからキャンバスへ

まず、DOMメソッドを使用してインラインSVG要素を選択する必要があります。 SVGにmy-svgidがあるとします。

const mySVG = document.getElementById('my-svg');

次に、 XMLSerializer を使用してSVGのコンテンツをシリアル化し、 btoa (ASCIIのバイナリ)を使用してそのbase64バージョンを作成します。

const xml = new XMLSerializer().serializeToString(mySVG);
const svg64 = btoa(xml);

次に、base64でエンコードされた文字列から直接ダウンロード可能なファイルを生成できますが、私が直面した問題は、ほとんどのブラウザが、ファイルとしてダウンロードするそのようなbase64でエンコードされた文字列のサイズに制限を課していることです。 だから私はその制限を回避するためにその時点から積み重ねなければなりませんでした。

新しいHTMLImage要素を作成し、そのsrcプロパティをSVGのbase64バージョンに設定します。

const image = new Image();
const b64Start = 'data:image/svg+xml;base64,';
image.src = b64Start + svg64;

これで、SVGのミラーイメージを含む実際のHTMLイメージ要素がページに表示されたので、それをCanvas2Dコンテキストに描画できます。

まず、画像のサイズに合わせてCanvas2Dコンテキストを作成する必要があります。 idmy-canvasのキャンバス要素がページに既にあると仮定します。

const canvas = document.getElementById('my-canvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, image.naturalWidth, image.naturalHeight);

また、作成した画像要素でonloadイベントをリッスンして、キャンバスコンテキストオブジェクトに実際に描画することができます。

image.onload = () => {
  ctx.drawImage(image, 0, 0, image.naturalWidth, image.naturalHeight);
};

了解しました。これで、これらのすべてのシェナニガンが配置され、最終的にインラインSVGの結果がキャンバスオブジェクトに描画されました。 楽しい部分に移り、canvasの toBlob メソッドのおかげで、実際にダウンロード可能なファイルを生成できます。

toBlobを使用してダウンロード可能なJPEGまたはPNG画像を作成する

その名前が示すように、toBlobメソッドは、キャンバスに描画された画像をブロブに変換します。 ブロブは文字列のバイナリ表現であり、マシンにファイルとしてダウンロードできます。

toBlobは、最初にコールバック関数を引数として受け取ります。これは、blob自体を受け取ります。コールバックでは、blobで好きなことを実行できます。 toBlobには、2つの追加の引数、mimeタイプ(デフォルトはimage/png)と、0(0%品質)から1(100%品質)までの数値が役立つ品質を指定することもできます。 image/jpegのような損失の多いmimeタイプを使用する場合。

たとえば、これにより、90%の品質でJpegブロブが作成されます。

canvas.toBlob(
  blob => {
    // do something with the blob here...
  },
  'image/jpeg',
  0.9,
);

URL.createObjectURL

私たちにできることは、 URL.createObjectURL を使用して、現在メモリ内にあるBLOBからURLを作成することです。

ページ上のアンカータグを選択し、そのhref属性を次のURLに設定するだけです。

canvas.toBlob(
  blob => {
    const anchor = document.getElementById('download-link');
    anchor.href = URL.createObjectURL(blob);
  },
  'image/jpeg',
  0.9,
);

次に、ユーザーはアンカーをクリックするだけでファイルのダウンロードを開始できます。


しかし、もっとうまくやって、ファイルのダウンロードを自動的に開始させることができるので、ちょっとしたトリックを使用して、プログラムでアンカー要素(a)を作成し、プログラムでクリックして自動的にクリックしますダウンロードをトリガーします。

canvas.toBlob(
  blob => {
    const anchor = document.createElement('a');
    anchor.download = 'my-file-name.jpg'; // optional, but you can give the file a name
    anchor.href = URL.createObjectURL(blob);

    anchor.click(); // ✨ magic!

    URL.revokeObjectURL(anchor.href); // remove it from memory and save on memory! 😎
  },
  'image/jpeg',
  0.9,
);

自動ダウンロードされたイメージを使用すると、生成されたBLOBからURLへのマッピングをメモリから解放/クリーンアップできることにも気付くでしょう。これで、BLOBがマシンにファイルとしてダウンロードされ、作業が完了しました。

まとめ

これは、必要なものを手に入れるために多くのことをやりくりしているように見えるかもしれませんが、これは、一度行ってから、ファンシーパンツアプリの実際の機能に焦点を当てることに戻るようなセットアップです。 さらに、保存したいものがキャンバスコンテキストに描画されると、toBlobメソッドを使用すると、アプリのニーズに最適な形式と品質でファイルを簡単に保存できます。