2011-08-11 17 views
9

Gram z elementem canvas w HTML5 i zauważyłem dziwne zachowanie. Przy początkowym załadowaniu wyświetlany obraz nie jest wyświetlany. Jednak po odświeżeniu przeglądarki wyświetla się odpowiednio. Użyłem IE9 i Chrome. Oba zachowują się identycznie. Kod JavaScript wygląda następująco:Dlaczego obraz nie wyświetla się po załadowaniu, ale wyświetla się po odświeżeniu?

window.onload = load; 
function load() { 
    var canvas = document.getElementById("canvas"); 
    var context = canvas.getContext("2d"); 
    context.fillRect(0, 0, 640, 400); 
    var image = new Image(); 
    image.src = "Images/smiley.png"; 
    context.drawImage(image, 50, 50); 
} 

Prostokąt słusznie zwraca zarówno razy, to uśmieszek, który pokazuje tylko na odświeżeniu przeglądarki.

Jestem w trakcie nauki HTML5 i JavaScript. Jestem pewien, że robię coś głupiego, ale nie mogę tego rozgryźć.

Odpowiedz

17

Obrazy ładują się asynchronicznie, więc dopiero po odświeżeniu wczytują się wystarczająco wcześnie, ponieważ są buforowane. Zwykle nie jest jeszcze załadowany w momencie, gdy dzwonisz pod numer drawImage. Użyj onload:

var image = new Image(); 
image.src = "Images/smiley.png"; 
image.onload = function() { 
    context.drawImage(image, 50, 50); 
}; 
+0

Dzięki. Wiedziałem, że to coś prostego. –

3

Stało się ze mną, jak również (tylko dla IE9 dla mnie) tak czy inaczej, znalazłem proste rozwiązanie.

Ustaw tło płótna na początkowy obraz, który chcesz wyświetlić.

var canvas = document.getElementById("canvas"); 
canvas.style.background="url('image.png')"; 

To powinno zadziałać!

+0

pimvdb, które właśnie sobie uświadomiłem, to prawdopodobnie lepszy sposób. – Jacob

0

W rzeczywistości, nawet po prostu przy użyciu image.onload = function() {}, nadal można napotkać problemy. Wykorzystaj tę technikę (to wcale nie jest to, co mówię), ale przenieś ją na dół strony.

Jako przykład, mam serwis społecznościowy, który używa płótna, aby pokazać zdjęcie profilowe (URI przechowywane w bazie danych) i wydrukować go na płótnie, a następnie nałożyć logo.

<section id="content"> 
    <article id="personalbox" > 
     <h2>Hi! My name is {profile_name}</h2> 
     <a id="friendbutton" href=""><img src="views/default/images/friend.png" width="12" height="12" /><span>Add {profile_name} as a friend?</span></a> 
     <video id="profilevideo" width="240" height="144">DEBUG: Video is not supported.</video> 
     <canvas id="profilecanvas" width="240" height="144" >DEBUG: Canvas is not supported.</canvas> 
     <a id="gallerytextlink" href="gallery.html" >Click to visit {profile_name} Gallery</a> 
     <table id="profileinfotable1"> 

...

</section> 

<script type="text/javascript"> 
    function init() { 
    var cvs = document.getElementById("profilecanvas"); 
    var ctx = cvs.getContext("2d"); 
    var img = new Image(); 
    img.src = "uploads/profile/{profile_photo}"; 
    img.onload = function() { 
     // Ignore. I was playing with the photo. 
     ctx.drawImage(img, 42, 32, 186, 130, cvs.width/2 - (186-42)/2, cvs.height/2 - (130-32)/2, 186-42, 130-32); 
     drawLogo(cvs,ctx); 
    } 
    } 

    function drawLogo(cvs,ctx) { 
    var logo   = "Enter Logo Here."; 
    ctx.fillStyle  = "rgba(36,36,36,0.6)";   
    ctx.strokeStyle = "rgba(255,255,255,0.3)"; 
    ctx.font   = "bold italic 6pt Serif"; 
    ctx.textAlign  = "left"; 
    ctx.textBaseline = "middle" ; 

    ctx.save(); 
    ctx.strokeText(logo, 4, cvs.height-11); 
    ctx.strokeText(logo, 6, cvs.height-11); 
    ctx.strokeText(logo, 4, cvs.height-9); 
    ctx.strokeText(logo, 6, cvs.height-9); 
    ctx.fillText(logo, 5, cvs.height-10); 
    ctx.restore(); 
    } 

    window.onload = init; 
</script> 

Najlepiej, by przejść całą drogę na dole przed znacznikiem końca </body>, ale umieścić go wyżej, ponieważ z mojego systemu szablonów. Wydaje się, że daje to czas na załadowanie obrazu po narysowaniu elementu canvas na ekranie i jest gotowy do odbioru danych wejściowych.

Nie mogę polegać na ustawianiu tła płótna i nie mam ochoty walczyć z odświeżeniami. Z jakiegoś powodu samo dodanie skryptu z img.onload = function() {} nie wystarczyło. Przesuń go niżej i oszczędzaj sobie bólów głowy.

Powiązane problemy