tutorial fabrics event javascript html canvas fabricjs

javascript - fabrics - Descargar Canvas como PNG en fabric.js dando error de red



fabrics js demo (3)

Dado que las dos respuestas anteriores solo funcionan para dataURL que tienen datos base64, y como esta pregunta ha sido mencionada por preguntas más generales relacionadas con "errores de red" debido a que los atributos href son demasiado grandes, aquí está el código que estoy usando:

// must be called in a click handler or some other user action var download = function(filename, dataUrl) { var element = document.createElement(''a'') var dataBlob = dataURLtoBlob(dataUrl) element.setAttribute(''href'', URL.createObjectURL(dataBlob)) element.setAttribute(''download'', filename) element.style.display = ''none'' document.body.appendChild(element) element.click() var clickHandler; element.addEventListener(''click'', clickHandler=function() { // ..and to wait a frame requestAnimationFrame(function() { URL.revokeObjectURL(element.href); }) element.removeAttribute(''href'') element.removeEventListener(''click'', clickHandler) }) document.body.removeChild(element) } // from Abhinav''s answer at https://stackoverflow.com/questions/37135417/download-canvas-as-png-in-fabric-js-giving-network-error/ var dataURLtoBlob = function(dataurl) { var parts = dataurl.split('',''), mime = parts[0].match(/:(.*?);/)[1] if(parts[0].indexOf(''base64'') !== -1) { var bstr = atob(parts[1]), n = bstr.length, u8arr = new Uint8Array(n) while(n--){ u8arr[n] = bstr.charCodeAt(n) } return new Blob([u8arr], {type:mime}) } else { var raw = decodeURIComponent(parts[1]) return new Blob([raw], {type: mime}) } }

Con estas funciones puedes cambiar el código a esto:

document.getElementById("downloadPreview").addEventListener(''click'', function() { var dataURL = _canvasObject.toDataURL({format: ''png'', multiplier: 4}) download("hellowWorld.png", dataURL) })

Quiero descargar Canvas como PNG usando fabric.js. Mientras descargo quiero escalar la imagen. Entonces uso la propiedad multiplier de la función toDataURL() . Pero me falla el error de red

PD: Si no doy la propiedad del multiplier , se está descargando, pero quiero usar la propiedad del multiplier ya que tengo que escalar la imagen.

Esto es lo que estoy haciendo:

Código HTML:

<canvas width="400" height="500" id="canvas" ></canvas> <a id=''downloadPreview'' href="javascript:void(0)"> Download Image </a>

JS

document.getElementById("downloadPreview").addEventListener(''click'', downloadCanvas, false); var _canvasObject = new fabric.Canvas(''canvas''); var downloadCanvas = function(){ var link = document.createElement("a"); link.href = _canvasObject.toDataURL({format: ''png'', multiplier: 4}); link.download = "helloWorld.png"; link.click(); }


El problema al que te enfrentas no está directamente relacionado con fabricjs (ni lienzo ni javascript por cierto), pero se debe a las limitaciones que algunos navegadores (incluido Chrome) tienen en la longitud máxima del atributo src de un elemento de anclaje ( <a> ) con el atributo de descarga.

Cuando se alcanza este límite, entonces lo único que tienes es este "Error de red" que no se puede bloquear en la consola; La descarga falló, pero usted como desarrollador no puede saberlo.

Tal como se propone en este duplicate (usted se niega a marcar-como-) , la solución es obtener directamente un Blob cuando esté disponible (para canvas, puede llamar a su método toBlob() , o convertir primero su dataURI a un Blob, y luego crear una URL de objeto de este Blob.

Fabricjs no parece tener una función toBlob implementada aún, por lo que en su caso exacto, tendrá que hacerlo más tarde.
Puede encontrar muchas secuencias de comandos para convertir dataURI a Blob, una está disponible en el método polyfill de MDN a Canvas.toBlob() .

Entonces se vería así:

// edited from https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob#Polyfill function dataURIToBlob(dataURI, callback) { var binStr = atob(dataURI.split('','')[1]), len = binStr.length, arr = new Uint8Array(len); for (var i = 0; i < len; i++) { arr[i] = binStr.charCodeAt(i); } callback(new Blob([arr])); } var callback = function(blob) { var a = document.createElement(''a''); a.download = fileName; a.innerHTML = ''download''; // the string representation of the object URL will be small enough to workaround the browser''s limitations a.href = URL.createObjectURL(blob); // you must revoke the object URL, // but since we can''t know when the download occured, we have to attach it on the click handler.. a.onclick = function() { // ..and to wait a frame requestAnimationFrame(function() { URL.revokeObjectURL(a.href); }); a.removeAttribute(''href'') }; }; dataURIToBlob(yourDataURL, callback);


Entiendo. Lo resolví como lo sugirió Kaiido.

function dataURLtoBlob(dataurl) { var arr = dataurl.split('',''), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while(n--){ u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], {type:mime}); }

NOTA: obtuve la función anterior de HTML5 / Javascript - DataURL a Blob & Blob a DataURL

var downloadCanvas = function(){ var link = document.createElement("a"); var imgData = _canvasObject.toDataURL({ format: ''png'', multiplier: 4}); var strDataURI = imgData.substr(22, imgData.length); var blob = dataURLtoBlob(imgData); var objurl = URL.createObjectURL(blob); link.download = "helloWorld.png"; link.href = objurl; link.click(); }