javascript canvas drawimage 可以在 iPhone 上使用吗?

Does javascript canvas drawimage work on iPhones?

我有一个网页,它从输入加载图像并调整大小和旋转,使其始终为纵向并显示在屏幕上。 这适用于桌面浏览器和 android,但不适用于我的朋友 iPhone。

function showImage(){
var input = document.getElementById("card");
    var filesToUpload = input.files;
    var file = filesToUpload[0];

    var img = document.createElement("img");
    var reader = new FileReader();

    reader.onload = function (e) {
        img.src = e.target.result
    }

    reader.onloadend = function () {
        var canvas = document.createElement("canvas");

        var width = img.width;
        var height = img.height;

        var ctx = canvas.getContext("2d");

        canvas.width = width;
        canvas.height = height;

        ctx.drawImage(img, 0, 0, width, height);

        var imgloc = document.getElementById("cardloc");

        imgloc.appendChild(canvas);

    }
    reader.readAsDataURL(file);}


<input id="card" name="card" type="file" accept="image/*" capture/>
<button type=button id="chooseButton" name="chooseButton" onclick="showImage()">
    Choose A card
</button>
<div id="cardloc"></div>

这是代码的精简版,没有调整大小和旋转来演示问题。在工作时,您可以看到 img.src 填充了编码图像,并且 canvas.toDataURL() 也返回了编码图像。 在 iphone 上 img.src 已填充,但 canvas.toDataURL() 未填充,只有 6 个字符长表示未加载图像。

我完全没有想法,有人可以帮忙吗?

当然可以(虽然我手头没有 iPhone)。

这里的问题是加载图像是一个异步任务(它与 JavaScript 执行并行执行),即使源是 data:URL,而且你不能在 canvas.

上绘制尚未加载的图像

现在为什么它可以在某些浏览器上运行?因为你实际上也在执行绘图部分异步,但是在一个不相关的事件中。

底层有点复杂,但基本上 FileReader 在完成读取 Blob 时总是会触发两个不同的事件:onerroronloadendedonloadonloadendonloadend 在前一个之后触发。

此处您在 onload 事件中设置 <img>src,届时浏览器将开始加载图像。由于它来自一个数据:URL,它没有什么可做的(没有网络请求),所以当第二个事件(onloadend)触发时,它实际上可能已经已加载图像,因此可以在 canvas.
上绘制它 然而,这实际上是一种有效的方法。

正确的处理方法是等待图像的 onload 事件。

reader.onload = function (e) {
  img.onload = function () {

    var canvas = document.createElement("canvas");

    var width = img.width;
    var height = img.height;

    var ctx = canvas.getContext("2d");

    canvas.width = width;
    canvas.height = height;

    ctx.drawImage(img, 0, 0, width, height);

    var imgloc = document.getElementById("cardloc");

    imgloc.appendChild(canvas);

  };
  img.src = e.target.result
}
reader.readAsDataURL(file);

但是你在这里甚至不需要 FileReader,你最好使用 blob: URL 它只是一个指向磁盘上文件的指针,这样可以避免浪费内存,也可以避免一级回调地狱:

img.onload = function () {

  var canvas = document.createElement("canvas");

  var width = img.width;
  var height = img.height;

  var ctx = canvas.getContext("2d");

  canvas.width = width;
  canvas.height = height;

  ctx.drawImage(img, 0, 0, width, height);

  var imgloc = document.getElementById("cardloc");

  imgloc.appendChild(canvas);

}
img.src = URL.createObjectURL(file);

Ps:既然你说你也做裁剪,如果你在这个修复后仍然有问题与 Safari,那么我邀请你阅读这个 关于这个浏览器中的一个实际错误(我不能确定你面对的是你在这里给我们的东西)。

感谢您的帮助。

我知道异步调用。我只是没有发现 img 也有一个 onload。

img 加载发生在 reader 加载结束之后,在 android 上这不是问题,但在 iPhone 上却是问题。

所以我只需要将 reader.onloaded 更改为 img.onload,一切都很好。

非常感谢