简体   繁体   中英

How can I load image from url along side input type file to html5 canvas?

I'm working on this app where I need to upload image to an html5 canvas from both url as well as user's hard drive. I have the functionality already implemented for the user's input from hard drive but I don't know how to add an image from url.

The code I used to load from input type file are all inside the input's event listener. It has a lot of functions in it as the app requires text input on the image as well. So image from url should have the same functionality as well.

Please note that the imgObj is inside the event listener. I tried changing the img.src to a url to test it out, but even though the image loads, I can't download it anymore. The console throws this error:

Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
    at HTMLButtonElement.<anonymous>

Here's the code minus some functions which is unnecessary to show it here:

 const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const btnDownload = document.getElementById('btnDownload'); const fileUpload = document.getElementById('file-upload'); fileUpload.addEventListener('change', function(e) { let imgObj = new Image(); imgObj.onload = draw; imgObj.onerror = failed; imgObj.src = URL.createObjectURL(this.files[0]); // imgObj.src = 'https://static.vecteezy.com/system/resources/previews/000/094/478/original/free-abstract-pattern-vector.jpg'; // some functions to write on image }); function draw() { canvas.width = this.naturalWidth; canvas.height = this.naturalHeight; const nw = this.naturalWidth; const nh = this.naturalHeight; ctx.drawImage(this, 0, 0, nw, nh); }; function failed() { console.error("The provided file couldn't be loaded as an Image media"); }; btnDownload.addEventListener('click', () => { const a = document.createElement('a'); document.body.appendChild(a); a.href = canvas.toDataURL(); a.download = "canvas-image.png"; a.click(); document.body.removeChild(a); });
 <canvas id="canvas" width="800" height="500"></canvas> <input type="file" id="file-upload" /> <button id="btnDownload">Download</button>

So in short how can I add upload from url functionality by keeping upload from input functionality?

Note that the things inside the input listener are gonna be the same for upload from url functionality. So may be I have to do something with imgObj and img.src .

You're running into a CORS issue. CORS is a protocol meant to prevent websites from getting access to your data from other sites ( cross-origin data). Since images were around since the early days of the web, cross-origin image loading couldn't be blocked due to backward compatibility concerns, but getting access to such data could be blocked.

So when you draw a cross-origin image into a canvas, the canvas gets "tainted", such that there are many things you can no longer do with it, including retrieving its contents as a data URL. Images uploaded from the filesystem are safe, since the user has to opt in.

So in order to use the image data, you have to tell the browser that the image must be loaded in a cross-origin manner. You do that by setting the crossOrigin attribute or property:

<img src="https://static.vecteezy.com/system/resources/previews/000/094/478/original/free-abstract-pattern-vector.jpg" crossorigin>
let imgObj = new Image();
imgObj.src =
      "https://static.vecteezy.com/system/resources/previews/000/094/478/original/free-abstract-pattern-vector.jpg";
imgObj.crossOrigin = "";

With this attribute/property, if the image doesn't support CORS, the load will fail and it won't even display. But if it does, as in this case, you'll be able to get the image data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM