canvas.toDataURL() for large canvas

后端 未结 4 2230
孤城傲影
孤城傲影 2020-11-30 06:21

I have a problem with .toDataURL() for large canvas. I want to enconde in base64 and decode on php file but if I have a large canvas the strD

4条回答
  •  生来不讨喜
    2020-11-30 06:54

    I'm not sure if there are limitation to canvas dimensions, but data urls have limitations depending on the browser: Data URL size limitations.

    What you could try is using Node.js + node-canvas (server side) to recreate the canvas. I've been using these for creating printable images from canvas elements, and didn't have any problems/limitations using toDataURL so far.

    Are you using the fabric.js library? I noticed you posted on their forum as well. Fabric.js can be used in Node.js and has a toDataURLWithMultiplier method, which scales the canvas/context allowing you to change the dataurl image size. You can check the method source to see how this is done.

    Edit:

    Since you're using fabric.js I would suggest using Node.js to handle the canvas to image processing on the server. You'll find more info on how to use fabric.js on Node.js here.

    Here is a simple server using Node.js and 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);
    

    When the server is running you can send data to it (postData). The server expects json, width and height to recreate the canvas, and a multiplier to scale the data url image. The client side code would look something like this:

    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);
        }
    });
    

提交回复
热议问题