Dane Base64 PNG do kanwy HTML5

89

Chcę załadować obraz PNG zakodowany w Base64 do elementu Canvas. Mam ten kod:

<html>
<head>
</head>
<body>
<canvas id="c"></canvas>
<script type="text/javascript">

var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");

data =  "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oMCRUiMrIBQVkAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAADElEQVQI12NgoC4AAABQAAEiE+h1AAAAAElFTkSuQmCC";

ctx.drawImage(data, 0, 0);

</script>
</body>
</html>

W Chrome 8 pojawia się błąd: Uncaught TypeError: Type error

A w Firebug Firefoksa to: „Typ obiektu jest niezgodny z oczekiwanym typem parametru skojarzonego z obiektem” kod: „17”

W tym base64 jest czarny kwadrat PNG o wymiarach 5x5px, który utworzyłem w GIMP i zamieniłem go na base64 w programie base64 GNU / Linuksa.

Tomáš Nesrovnal
źródło

Odpowiedzi:

170

Wygląda na to, że musisz przekazać drawImage taki obiekt obrazu

var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");

var image = new Image();
image.onload = function() {
  ctx.drawImage(image, 0, 0);
};
image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oMCRUiMrIBQVkAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAADElEQVQI12NgoC4AAABQAAEiE+h1AAAAAElFTkSuQmCC";
<canvas id="c"></canvas>

Wypróbowałem to w chromie i działa dobrze.

Jerryf
źródło
8
Dobra odpowiedź, ale czy na pewno to działa za każdym razem? Znalazłem błędne rysowanie obrazu natychmiast po ustawieniu src, ponieważ powinieneś użyć onloadwywołania zwrotnego, aby upewnić się, że obraz został załadowany. 50% moich testów zakończyło się niepowodzeniem, ponieważ ładowanie obrazu nie zostało zakończone.
Scott Rippey
Łał! Powiew przeszłości :). Masz całkowitą rację. Jeśli wywołujesz drawImage zaraz po ustawieniu src obrazu prawdopodobnie napotkasz problemy iw zależności od sytuacji najprawdopodobniej będziesz chciał użyć onload, aby upewnić się, że obraz jest faktycznie załadowany przed próbą renderowania to do płótna. Powyższy kod był po prostu bardziej przykładem pokazującym, że drawImage faktycznie wymaga obiektu obrazu i jak go do niego przekazać.
Jerryf,
8
Uwaga: jeśli zapętlasz kilka płócien, możesz zmienić to na, ctx.drawImage(this,0,0);aby zapewnić, że zmienna obrazu odwołuje się do właściwego obrazu. Świetna odpowiedź!
Dormouse
13
Zdarzenie onload należy ustawić przed src. Czasami src można załadować natychmiast i nigdy nie uruchamiać zdarzenia onload
Totty.js
3
Ale jeśli data:image/długość jest duża, otrzymamy414 (Request-URI Too Long
Sarath
17

Odpowiedź Jerryfa jest w porządku, z wyjątkiem jednej wady.

Zdarzenie onload należy ustawić przed src. Czasami src można załadować natychmiast i nigdy nie uruchamiać zdarzenia onload.

(Jak wskazał Totty.js.)

var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");

var image = new Image();
image.onload = function() {
    ctx.drawImage(image, 0, 0);
};
image.src = "data:image/  png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oMCRUiMrIBQVkAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAADElEQVQI12NgoC4AAABQAAEiE+h1AAAAAElFTkSuQmCC";
Jan
źródło
2
Btw: zredagowałem odpowiedź Jerryfa, ale ktoś ją odrzucił. To nie mógł być Jerryf, jak podaje jego profil, ostatnio był zalogowany w 2014 roku.
John
2
„Czasami src można załadować natychmiast i nigdy nie uruchamiać zdarzenia onload”. Myślę, że zdarzenie to jest niezwykle rzadkie, a prawie nigdy, ale nie ma powodu, aby nie robić tego onloadwcześniej src... Robię to nawykiem.
markE
2
@markE Nie jest to rzadkie. Będzie się to działo przez cały czas, gdy przeglądarka buforuje obraz, na przykład podczas ponownego ładowania przeglądarki. Stało się to w silniku IE w programie C ++.
Stefan Rein