您的位置:首页 > 移动开发 > 微信开发

关于图片onload事件兼容性处理, 谷歌浏览器版本 56.0.2896.3 (64-bit) 微信客户端浏览器 canvas篇

2016-11-15 10:59 609 查看

关于图片onload事件兼容性处理

阐述:

一个小demo,关于canvas 绘制 大转盘 指针,当同时各自添加onload事件指针图片突发性不显示.

兼容性问题-浏览器版本: 谷歌浏览器版本 56.0.2896.3 (64-bit) , 微信客户端浏览器(iphone6)

PC平台 :WIN10(64-bit)

代码实例

function runLottey(Elem) {
// 1. 获取画布对象
var context = Elem.getContext('2d')
const WIDTH = Elem.width;
const HEIGHT = Elem.height;
// 2.绘制大转盘
var as = new Image();
as.src = "img/as.png";
as.onload = function () {
context.drawImage(as, 0, 0);
};
// 3.绘制指针
var pin = new Image();
pin.src = "img/pin.png";
var pinwidth = 358;
var pinheight = 301;
pin.onload= function () {
context.drawImage(pin, (WIDTH / 2 - pinwidth / 2 +10) , (HEIGHT / 2 - pinheight / 2 -10));
};
}


实例效果图:



问题:

1.为什么指针会消失?

2.指针是否被绘制?

3.如何处理指针显示不正常问题?

观点整理:

1

HTML5在使用drawImage绘图的时候,出现刷新就不显示的问题,原来要想是图片正常显示需要为图片添加一个onload事件.

2

setTimeout 计时器上绑定的函数不会立即执行 (不被立即执行的原因是JavaScript是单线程的)。实际上,被延迟的函数将依次排在执行队列的最后,等待下一次恰当的时间再执行。

3

若先给设置src属性,第一次浏览器执行完赋值src的语句后就要去加载图片,这个过程是很慢的,而此时程序已经执行完赋值语句,就不会等待是否加载完再执行下一条语句而是直接继续执行,然后开始给onload赋值函数,而赋值这个事件相对于从网上加载图片的时间是很短的,所以就可以执行onload函数了。假设有缓存,当执行完src的赋值语句后浏览器瞬间加载完图片,这个速度快到程序还没有执行到onload的赋值语句,所以此时onload事件被触发但此时还没有给onload事件赋值赋值,所以执行onload函数时为空函数,什么都不执行。

4

做过图片翻转效果的朋友其实都知道,要让图片轮换的时候不出现等待,最好是先让 图片下载到本地,让浏览器缓存起来。这时,一般都会用到js里边的Image对象。一般的手段无非这样:

function preLoadImg(url) {
  var img = new Image();
  img.src = url;
}


5

通过onload就能获取到图片的宽高了。但onload大一点的图通常都比较慢,不实用,但只要图片被浏览器缓存,那么图片加载几乎就不用等待即可触发onload,我们要的是占位符。所以有些人通过缓存获取也可以这么写。

//通过complete与onload一起混合使用为了测试缓存效果,注意以下测试图片的url都不加时间戳

// 图片地址
var img_url = 'http://www.qttc.net/static/upload/2013/13643608813441.jpg';

// 创建对象
var img = new Image();

// 改变图片的src
img.src = img_url;

// 判断是否有缓存
if(img.complete){
// 打印
alert('from:complete : width:'+img.width+',height:'+img.height);
}else{
// 加载完成执行
img.onload = function(){
// 打印
alert('from:onload : width:'+img.width+',height:'+img.height);
};
}


第一次执行,永远是onload触发



你再刷新,几乎都是缓存触发了



本菜鸟观点:

onload加载过快导致无法绘制指针.

通过多次实验测试,以及各位前人的观点分析,比较认同onload过快执行导致图片在已经赋值但没有加载完的情况下已经开始渲染了这样的观点.

在canvas中 绘制图片 不管url前置还是后置 在当前版本谷歌浏览器中都是无法加载完图片进行绘制.

但是如果我刷新页面进行等待3s,却能不时看到指针绘制成功

这时候有两种可能 图片加载慢 或 onload过快 所以我想到了用 setTimeout 延迟绘制时间,进行异步绘制. 结果是成功的.



在这个图表中有许多信息需要理解,如果完全理解了它们,你会对JavaScript引擎如何实现异步事件有一个很好的认识。这是一个一维的图标:垂 直方向表示时间,蓝色的区块表示JavaScript代码执行块。例如第一个JavaScript代码执行块需要大约18ms,鼠标点击所触发的代码执行 块需要11ms,等等。由于JavaScript引擎同一时间只执行一条代码(这是由于JavaScript单线程的性质),所以每一个JavaScript代码执行块会“阻塞”其它异步事件的执行。这就意味着当一个异步事件发生(例如,鼠标点击,计时器被触发,或者Ajax异步请求)后,这些事件的回调函数将排在执行队列的最后等待执行(实际上,排队的方式根据浏览器的不同而不同,所以这里只是一个简化);

解决方法:

function runLottey(Elem) {
// 1. 获取画布对象
var context = Elem.getContext('2d')
const WIDTH = Elem.width;
const HEIGHT = Elem.height;
var as = new Image();
as.src = "img/as.png";
as.onload = function () {
context.drawImage(as, 0, 0);
};
var pin = new Image();
pin.src = "img/pin.png";
var pinwidth = 358;
var pinheight = 301;
pin.onload= function () {
//此处增加一个异步setTimeout
setTimeout(function () {
context.drawImage(pin, (WIDTH / 2 - pinwidth / 2 +10) , (HEIGHT / 2 - pinheight / 2 -10));
},0);
};
}


**

总结: setTimeout异步方法可以让图片绘制放在队列后面以致于不会出现空绘. 但真的是这样吗?

期待大神们指导 ——
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐