一、問題源碼:java
<p>要使用的圖像:</p> <img id="tulip" src="/i/eg_tulip.jpg" alt="The Tulip" /> <p>畫布:</p> <canvas id="myCanvas" width="500" height="300" style="border:1px solid #d3d3d3;background:#ffffff;"> Your browser does not support the HTML5 canvas tag. </canvas> <script> var c=document.getElementById("myCanvas"); var ctx=c.getContext("2d"); var img=document.getElementById("tulip"); ctx.drawImage(img,10,10); </script>
二、解決辦法:canvas
在併發
ctx.drawImage(img,10,10);
外面套一層:異步
img.onload=function(){ ctx.drawImage(img,10,10); }
三、緣由分析:spa
圖片的加載是異步的,它會在本身後面的非異步代碼執行完以後,再開始執行本身3d
異步猛一看有點併發的感受,其實仍是排隊,且仍是排的原來那條隊,時間並無被節省,只不過它會在輪到本身時,放棄本身的位置,主動站到非異步的代碼隊尾,非異步的都執行完再輪到本身時,纔開始執行本身的,它後面其餘的異步對象也是如此,不事後面異步的對象會等前面的異步執行了以後再執行,不過不會等待前面的異步執行完才執行。有點Gentleman的趕腳!code
js中全部事件都是異步的,onload也是,onload的異步在圖片異步以後,因此onload會在圖片加載以後執行,同時onload除了異步以外,它仍是個事件,也就是圖片加載了以後纔會觸發,因此使用onload是百分百能夠看到圖片對象
同時若是不使用onload,使用隊列
setTimeout(function(){ ctx.drawImage(img,10,10); },0);
也會看到圖片被繪製出來,不過不是穩定的,偶爾看不到。緣由就是事件
setTimeout
製造了一個異步,即便等待時間是0,這就意味着它成了一個圖片加載異步以後的一個異步,圖片加載先執行,它後執行,假如圖片加載的快,它就繪製成功,慢了,它就失敗。若是沒有了
setTimeout
就百分百失敗,由於繪製圖片的代碼所在的子隊列在圖片異步以前,圖片會等到它執行完了,纔剛剛開始本身的加載工做
PS:
一、火狐彷佛是個特例,它不用那些麻煩事,直接w3school拷貝下來的實例代碼,刷新下就能夠正常訪問了,這是爲啥?
二、w3school上拷貝的代碼雖然本地不能繪製成功,但是在線,在它的實例執行頁面看效果確實正常的,這怎麼解釋呢?
有路過的大神,還請賜教~