canvas.toDataURL() for large canvas
我的大画布
我的代码:
1 2 3 4 5 6 | var strDataURI = canvas.toDataURL(); strDataURI = strDataURI.substr(22, strDataURI.length); $.post("save.php", { str: strDataURI }; |
是否可以使用
谢谢。
我不确定画布尺寸是否有限制,但是数据URL取决于浏览器是否有限制:数据URL大小限制。
您可以尝试使用Node.js + node-canvas(服务器端)重新创建画布。我一直在使用这些从画布元素创建可打印图像,并且到目前为止,使用toDataURL都没有任何问题/限制。
您正在使用fabric.js库吗?我注意到您也张贴在他们的论坛上。
Fabric.js可以在Node.js中使用,并具有toDataURLWithMultiplier方法,该方法可以缩放画布/上下文,从而允许您更改dataurl图像大小。您可以检查方法源以了解如何完成。
编辑:
由于您使用的是fabric.js,因此建议您使用Node.js来处理画布上服务器上的图像处理。您可以在此处找到有关如何在Node.js上使用fabric.js的更多信息。
这是一个使用Node.js进行表达的简单服务器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | 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); |
服务器运行时,可以向其发送数据(
服务器期望
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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); } }); |
您应该首先考虑这一点:上传的大小是有限的。该限制取决于浏览器,操作系统和服务器环境。您可以看一下这篇文章:http://www.motobit.com/help/scptutl/pa98.htm
通常,您可以尝试如下操作:
首先,我们需要一个函数将dataURI转换为Blob:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | function convertDataURItoBlob(dataURI) { 'use strict' var byteString, mimestring if(dataURI.split(',')[0].indexOf('base64') !== -1 ) { byteString = atob(dataURI.split(',')[1]) } else { byteString = decodeURI(dataURI.split(',')[1]) } mimestring = dataURI.split(',')[0].split(':')[1].split(';')[0] var content = new Array(); for (var i = 0; i < byteString.length; i++) { content[i] = byteString.charCodeAt(i) } var rawContent = new Uint8Array(content), returnBlob = new Blob([rawContent], {type: mimestring}) return returnBlob; } |
接下来是使用XMLHttpRequest2上传文件的功能:
1 2 3 4 5 6 7 | function upload(blob) { var xhr = new XMLHttpRequest(); xhr.open('POST', '/yourServerEndPoint', true); xhr.onload = function(e) { ... }; xhr.send(blob); } |
现在,您可以将
您可以在这里更深入地了解XMLHTTPRequest2:http://www.html5rocks.com/en/tutorials/file/xhr2/
以及有关Blob构造函数的信息:https://developer.mozilla.org/en-US/docs/DOM/Blob
您始终可以将图像分成较小的部分,然后分别保存,这可能不是一个坏主意。基本上你会有一个类似
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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. } } |
更新了代码,将画布拆分为较小的画布对象。效果很好,还添加了跟踪器:
这样可以跟踪上传过程,总体上我认为对用户更好。我在稍后使用PHP重新加入。
它避免了画布/浏览器等尺寸的问题。
我的第一篇文章,希望对您有所帮助!
//输入文件名的类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | function sliceCanvas(type, canvasId){ var largeCanvas = document.getElementById(canvasId).getContext('2d'); var slice = document.createElement('canvas').getContext('2d'); var baseSize = 500; fileH = largeCanvas.canvas.height / baseSize; fileW = largeCanvas.canvas.width / baseSize; slice.canvas.width = baseSize; slice.canvas.height = baseSize; count = 1; numFiles = Math.ceil(fileH) * Math.ceil(fileW); for (var y=0; y < largeCanvas.canvas.height; y+=baseSize){ for (var x=0; x < largeCanvas.canvas.width; x+=baseSize){ slice.clearRect(0, 0, slice.canvas.width, slice.canvas.height); slice.drawImage(largeCanvas.canvas, x, y, baseSize, baseSize, 0, 0, baseSize, baseSize); var imagePiece = slice.canvas.toDataURL(); typeFinal = type + count; exportSlice(typeFinal, imagePiece, numFiles); count++; } } } |
要上传的Ajax:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | function exportSlice(type, dataURL, fileNum){ percent = 0; percentComplete = 0; $.ajax({ type:"POST", url: YourServerSideFiletoSave, data: {image: dataURL, type: type} }) .done(function( response ) { console.log(response); percent++; percentComplete = Math.ceil(Number(percent/fileNum*100)); return true; }) .fail(function(response) { console.log("Image FAILED"); console.log(response); return false; }) .always(function(response) { console.log("Always"); }); } |