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 时总是会触发两个不同的事件:onerror 和 onloadended或 onload 和 onloadend,onloadend 在前一个之后触发。
此处您在 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,一切都很好。
非常感谢
我有一个网页,它从输入加载图像并调整大小和旋转,使其始终为纵向并显示在屏幕上。 这适用于桌面浏览器和 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 时总是会触发两个不同的事件:onerror 和 onloadended或 onload 和 onloadend,onloadend 在前一个之后触发。
此处您在 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,一切都很好。
非常感谢