简体   繁体   中英

Input onchange javascript function call not working in Safari

I have an html canvas that shows a preview of an image when the image is selected in an input. This works in Chrome, but I can't seem to get it to work in Safari. Specifically - in Safari - the onchange="previewFile()" does not seem to call the previewFile function.

 <canvas id="canvas" width="0" height="0"></canvas> <h2>Upload a photo </h2> <input type="file" onchange="previewFile()"><br> <script type="text/javascript"> // setup the canvas var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); // grab the photo and display in canvas var photo = new Image(); function previewFile() { var file    = document.querySelector('input[type=file]').files[0]; var reader  = new FileReader(); reader.addEventListener("load", function () { photo.src = reader.result; canvas.height = photo.height; canvas.width = photo.width; ctx.drawImage(photo,0,0); }, false); if (file) {  reader.readAsDataURL(file); } } </script> 

Your problem is certainly due to the fact that you are not waiting for the image has loaded before you try to draw it on the canvas.

Even wen the source is a dataURI, the loading of the image is asynchronous, so you need to wrap your drawing operations in the image's onload event.

var photo = new Image();
photo.onload = function(){
  canvas.height = photo.height;
  ...
  }
...
reader.onload = function(){
  // this will eventually trigger the image's onload event
  photo.src = this.result;
  }

But if all you need is to draw your image on the canvas, don't even use a FileReader, actually, the readAsDataURL() method should trigger a I'm doing something wrong error in your brain. Almost all you can do with a dataURI version of a Blob, you can also do it with the Blob itself, without computing it nor polluting the browser's memory.

For example, to display an image for user input, you can use URL.createObjectURL(blob) method.

 // setup the canvas var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); // grab the photo and display in canvas var photo = new Image(); // drawing operations should be in the mage's load event photo.onload = function() { // if you don't need to display this image elsewhere URL.revokeObjectURL(this.src); canvas.height = this.height; canvas.width = this.width; ctx.drawImage(this, 0, 0); } photo.onerror = function(e) { console.warn('file format not recognised as a supported image'); } file_input.onchange = function() { // prefer 'this' over DOM selection var file = this.files[0]; var url = URL.createObjectURL(file); photo.src = url; }; 
 <canvas id="canvas" width="0" height="0"></canvas> <h2>Upload a photo </h2> <input type="file" id="file_input"> <br> 

And for those who need to send this file to their server, use a FormData to send directly the Blob. If you really need a dataURI version, then convert it server-side.

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