勇士传说吧 关注:18,111贴子:6,243
  • 12回复贴,共1

开发心得:onload函数回调与for i循环间的冲突

只看楼主收藏回复

js中的new Image()对象有这样的写法
var img = new Image();
img.src = 'xxx/xxx.png';
img.onload = function(){.........};
在function里写canvas绘图的代码就可以制作游戏的场景、人物、动画等
不过在做游戏的过程中所要用到的素材肯定不只一张图,那么在多张图同时加载时该怎么写呢
下面的写法是错的
var str = '1.png,2.png,3.png';
var src= str.split( str );
var img = new Array( src.length );
for( i = 0, i < src.length; i++ )
{
img[i] = new Image();
img[i].src = src[i];
img[i].onload = function(){ canvasContext2d.drawImage( img[i], 0, 0 ) };
}
为什么错呢,因为onload function是异步的,如果.src加载出现问题,没有在下一句drawImage之前加载完的话(这是必然的,不然也不用写onload function了)下标i就会乱掉
也就是说当onload function开始执行时,i基本上都只等于src.length;,于是所有的drawImage都会执行drawImage( img[src.length], 0, 0 ) 这句,由于 img[src.length]是undefined的,所以就会出错,当然如果你的 src.length足够大,也不是一定出错,但绘图错乱是必然的,比如在该绘第一张图的时候i已经跑到1000了,于是在绘第一张图的位置绘了第1000张图的内容


IP属地:江苏本楼含有高级字体1楼2015-02-13 17:52回复
    于是我把方法写成这样,但依然是错的
    var draw = function( cvsctx, imgarr, num )
    {
    cvsctx.drawImage( imgarr[num], 0, 0, 32, 32, num*32, num*32, 32, 32 );
    }
    var img = new Array( new Image(), new Image() );
    img[0].src = 'test.php';
    img[1].src = 'static/image/map/TileA2.png';
    for( i = 0; i < 2; i++ )
    {
    img[i].onload = draw( mapctx, img, i );
    }
    这里的onload在赋值的时候居然没等画片加载完就直接执行了


    IP属地:江苏本楼含有高级字体2楼2015-02-13 18:27
    回复
      为了能让画片加载完才执行
      在onload后面套了个function,想也不用想,这肯定又回到了1楼上面的问题上


      IP属地:江苏3楼2015-02-13 18:31
      回复
        img[i].onload = (function( cvsctx, imgarr, num ){ cvsctx.drawImage( imgarr[num], 0, 0, 32, 32, num*32, num*32, 32, 32 ); })( mapctx, img, i );
        换成这样,其实和3楼的也没啥区别


        IP属地:江苏4楼2015-02-13 18:54
        回复
          所以暂时先放弃了
          var map = document.getElementById("map");
          var mapctx = map.getContext( '2d' );
          var img = new Array( new Image(), new Image() );
          img[0].src = 'test.php';
          img[1].src = 'static/image/map/TileA2.png';
          var num = img.length;
          if( 0 < num )
          {
          img[0].onload = function(){
          mapctx.drawImage( img[0], 0, 0, 32, 32, 0*32, 0*32, 32, 32 );
          }
          }
          if( 1 < num )
          {
          img[1].onload = function(){
          mapctx.drawImage( img[1], 0, 0, 32, 32, 1*32, 1*32, 32, 32 );
          }
          }
          多写几个if吧……不知道谁有更好的办法


          IP属地:江苏5楼2015-02-13 19:00
          回复
            在CSDN上求问到一个高手
            for( i = 0; i < img.length; i++ )
            {
            img[i].onload = function (i){
            return function(){ mapctx.drawImage( img[i], 0, 0, 32, 32, i*32, i*32, 32, 32) };
            }(i);
            }
            就这么愉快的解决了


            IP属地:江苏6楼2015-02-13 19:45
            收起回复
              百度到了这个帖子,解决了困扰了我4个小时的问题
              不过还是不太懂这个写法,为什么非要return一个函数,不这样写就不行,而且函数定义完之后的那个(i)是什么语法。。


              IP属地:上海7楼2016-07-08 20:50
              收起回复
                666我也遇到这个问题


                IP属地:陕西8楼2017-11-28 19:32
                回复