8

HTML5 Canvas には 1 つの問題があります。私は1つのイメージを持っています。この画像にテキストを入れて画像として表示・保存したいです。

私はこのコードを持っています:

window.onload = function(){
 var canvas = document.getElementById("myCanvas");
 var context = canvas.getContext("2d");
 var imageObj = new Image();
 imageObj.onload = function(){
     context.drawImage(imageObj, 10, 10);
     context.font = "20px Calibri";
     context.fillText("My TEXT!", 50, 200);
 };
 imageObj.src = "mail-image.jpg"; 
};

これはうまくいきます。私の画像とその上にテキストがあります。しかし、それはまだキャンバスであり、イメージではありません。誰でも私を助けることができますか?

4

2 に答える 2

15

セキュリティ上の理由から、キャンバスの描画をユーザーのローカル ドライブに保存する便利な方法はありません。

回避策として、「オールドスクール」に進みます。キャンバスを画像に変換し、新しいウィンドウに表示します。

window.onload = function(){
 var canvas = document.getElementById("myCanvas");
 var context = canvas.getContext("2d");
 var imageObj = new Image();
 imageObj.onload = function(){
     context.drawImage(imageObj, 10, 10);
     context.font = "20px Calibri";
     context.fillText("My TEXT!", 50, 200);

     // open the image in a new browser tab
     // the user can right-click and save that image
     var win=window.open();
     win.document.write("<img src='"+canvas.toDataURL()+"'/>");    

 };
 imageObj.src = "mail-image.jpg"; 
};
于 2013-09-12T16:58:49.587 に答える
6

サンドボクシング

ブラウザーは、コンテンツをユーザーのハードディスクに保存する際にサンドボックス化されます。これはセキュリティのためです (悪意のあるハッカー (またはスパイ) がシステム ファイルを上書きしたり、ウイルスやバックドアなどを仕掛けたりするのは望ましくありません)。したがって、直接アクセスは防止され、ローカル ストレージは分離されます。

操作を承認するユーザーの操作によって常にコンテンツを「ブリッジ」する必要があります。そのため、ブラウザーは、ブラウザーがコンテンツを配信しようとしていることをユーザーに知らせるダイアログをポップアップして、ファイルの場所を選択するように要求します。保存されます (以下のデモを参照)。

保存ダイアログの呼び出し

ダウンロードを有効にするその他の方法をいくつか示します。

たとえば、画像の下のリンクが問題ない場合は、次のことができます。

/// create an anchor/link (or use an existing)
var lnk = document.createElement('a');

/// set your image as data-uri link
lnk.href = canvas.toDataURL();

/// and the key, when user click image will be downloaded
lnk.download = 'filename.png';

/// add lnk to DOM, here after the canvas
canvas.parentElement.appendChild(lnk);

ダウンロード属性は、HTML5 の新しい機能です。この場所に「ナビゲート」する代わりに、ブラウザーは保存ダイアログを表示し、ユーザーがコンテンツをディスクに保存できるようにします。

イベントを生成することで、クリック機能全体を自動化することもできます。

例えば:

function download(canvas, filename) {

    if (typeof filename !== 'string' || filename.trim().length === 0)
        filename = 'Untitled';

    var lnk = document.createElement('a'),
        e;

    lnk.download = filename;        
    lnk.href = canvas.toDataURL();  

    if (document.createEvent) {

        e = document.createEvent("MouseEvents");
        e.initMouseEvent('click', true, true, window,
                         0, 0, 0, 0, 0, false, false,
                         false, false, 0, null);

        /// send event            
        lnk.dispatchEvent(e);

    } else if (lnk.fireEvent) {

        lnk.fireEvent("onclick");
    }
}

サーバーに保存

ファイルをサーバーに保存する手順はいつでも実行できます。ただし、サーバー (ダイアログ) からファイルを取得するときに、保存ダイアログの手順も実行する必要があります。

ブラウザに表示するためだけにファイルを保存したい場合、これは完璧です。

これを行うにはさまざまな方法があります (これには SO に関する多くのソリューションがあります)。

ローカルストレージ

別のオプションは、ファイルをブラウザのローカル ストレージに保存することです。Web Storageがありますが、これは非常に制限されており (通常は 2.5 から 5 mb)、格納される各文字が 2 バイトかかることを考慮すると、実際のストレージはその半分です (data-uri や data- などの文字列のみを格納できます)。 uris は元のファイルよりも約 33% 大きくなっています)。しかし、小さなアイコンやスプライトなどを保存すれば、これで十分かもしれません。

さらに、より大きなデータを保存できるIndexed DB (および現在廃止されているWeb SQL ) を使用でき、x mb のデータを保存するユーザーの許可を要求することもできます。

同じことがFile APIにも当てはまります(これは現在 Chrome でのみ実装されています)。これはファイル システムのように機能し、巨大なファイルを格納することを目的としています。

これらに慣れていない場合、これらはより複雑に見えるかもしれませんが、サーバーとの通信帯域幅を節約し、「負荷」をサーバーではなくクライアントに移動するため、可能なオプションとして言及します。

于 2013-09-12T18:08:00.460 に答える