10

.toDataURL()大きなキャンバスに問題があります。PHPファイルをエンコードしてデコードしたいbase64のですが、キャンバスが大きい場合、strDataURI変数は空です。

私のコード:

var strDataURI = canvas.toDataURL();
strDataURI = strDataURI.substr(22, strDataURI.length);
$.post("save.php",
{ 
   str: strDataURI
};

.toDataURL()サイズ制限を変更するための代替手段または方法はありますか?

ありがとう。

4

4 に答える 4

18

キャンバスのサイズに制限があるかどうかはわかりませんが、ブラウザによってデータ URL に制限があります:データ URL サイズの制限

試すことができるのは、Node.js + node-canvas (サーバー側) を使用してキャンバスを再作成することです。キャンバス要素から印刷可能な画像を作成するためにこれらを使用してきましたが、これまで toDataURL を使用して問題や制限はありませんでした。

fabric.js ライブラリを使用していますか? あなたが彼らのフォーラムにも投稿していることに気付きました。Fabric.js は Node.js で使用でき、キャンバス/コンテキストをスケーリングして dataurl 画像サイズを変更できるtoDataURLWithMultiplierメソッドがあります。メソッドのソースをチェックして、これがどのように行われるかを確認できます。

編集:

fabric.js を使用しているので、Node.js を使用して、サーバー上でキャンバスから画像への処理を処理することをお勧めします。Node.js で fabric.js を使用する方法の詳細については、こちらを参照してください。

Node.js と Express を使用した単純なサーバーを次に示します。

var express = require('express'),
    fs = require('fs'),
    fabric = require('fabric').fabric,
    app = express(),
    port = 3000;

var allowCrossDomain = function (req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'POST, OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type');
    next();
}

app.configure(function() {
    app.use(express.bodyParser());
    app.use(allowCrossDomain);
});

app.options('/', function(req, res) {
    res.send(200);
});

app.post('/', function(req, res) {
    var canvas = fabric.createCanvasForNode(req.body.width, req.body.height);
    
    console.log('> Loading JSON ...');
    canvas.loadFromJSON(req.body.json, function() {
        canvas.renderAll();
        
        console.log('> Getting PNG data ... (this can take a while)');
        var dataUrl = canvas.toDataURLWithMultiplier('png', req.body.multiplier),
            data = dataUrl.replace(/^data:image\/png;base64,/, '');
        
        console.log('> Saving PNG to file ...');
        var filePath = __dirname + '/test.png';
        fs.writeFile(filePath, data, 'base64', function(err) {
            if (err) {
                console.log('! Error saving PNG: ' + err);
                res.json(200, { error: 'Error saving PNG: ' + err });
            } else {
                console.log('> PNG file saved to: ' + filePath);
                res.json(200, { success: 'PNG file saved to: ' + filePath });
            }
        });
    });
});

app.listen(port);
console.log('> Server listening on port ' + port);

サーバーが稼働しているときは、サーバーにデータを送信できます ( postData)。jsonサーバーは、キャンバスを再作成し、データ URL 画像をスケーリングすることを期待widthしています。クライアント側のコードは次のようになります。heightmultiplier

var postData = {
    json: canvas.toJSON(),
    width: canvas.getWidth(),
    height: canvas.getHeight(),
    multiplier: 2
};

$.ajax({
    url: 'http://localhost:3000',
    type: 'POST',
    contentType: 'application/json; charset=utf-8',
    data: JSON.stringify(postData),
    dataType: 'json',
    success: function(data) {
        console.log(data);
    },
    error: function(err) {
        console.log(err);
    }
});
于 2013-04-23T15:48:54.673 に答える
2

いつでも画像を小さなセクションに分割し、それらを個別に保存することができますが、これはおそらく悪い考えではありません. 基本的に、次のような関数があります

var largeCanvas = document.getElementById('yourGiantCanvas').getContext('2d'),
    slice = document.createElement('canvas').getContext('2d');

slice.canvas.width = 1000;
slice.canvas.height = 1000;

for (var y=0; y < canvas.height; y+=1000){
  for (var x=0; x < canvas.width; x+=1000){
    slice.clearRect(0, 0, slice.canvas.width, slice.canvas.height);
    slice.drawImage(largeCanvas.canvas, x, y, 1000, 1000, 0, 0, 1000, 1000);

    var imagePiece = slice.canvas.toDataURL();

    //Now just save the imagePiece however you normally were planning to
    //and you can build the image again using these slices. You can create 
    //a much better user experience this way too. 
  }
}
于 2013-04-23T04:04:57.343 に答える