A HTML5-ös szabvány egy nagyon hasznos újítása a <CANVAS>
elem.
Ezzel egy raszteres rajzolási felületet hozunk létre a weboldalon, aminek tartalmát aztán JavaScript kódok segítségével alakíthatjuk.
A Canvas használata két részből áll.
Egyrészt definiálni kell a HTML kódban a rajzfelületet a <CANVAS>
elem segítségével, másrészt meg kell írni az azt "telerajzoló" JavaScript kódot.
Mivel a JavaScript kódban hivatkoznunk kell a <CANVAS>
elemre, biztosítanunk kell, hogy végrehajtásakor már létezzen a megfelelő objektum a DOM-ban.
Ezért vagy a <body onload="...">
konstrukciót használjuk, vagy a kódot a <CANVAS>
elem definiálása után illesszük a html kódba, ahogy az a következő példában is van:
<!doctype html> <html> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> <title>Canvas példák 1.</title> </head> <body> <h1>Canvas példák 1.</h1> <canvas id="rajz" width="400px" height="500px"></canvas> <script> var rajz=document.getElementById("rajz"); var rajzCt=rajz.getContext('2d'); with(rajzCt) { beginPath(); rect(100,200,200,200); moveTo(100,200); lineTo(200,60); lineTo(300,200); stroke(); } </script> </body> </html>1. példa: egyszerű vonalas rajz.
Látható, hogy a tulajdonképpeni rajzolási műveleteket nem közvetlenül a Canvas objektumon, hanem egy úgynevezett "drawing context"-en (magyarul ???) hajtjuk végre.
Ezt a context objektumot a Canvas getContext('2d')
metódusával kapjuk meg. A rajzoló utasításokat a context objektum különféle metódusainek meghívásával adhatjuk ki.
Vonalas rajz esetén az azonos rajzi tulajdonságokal (szín, vastagság, kitöltés) rendelkező elemeket egy beginPath()
és egy stroke()
utasítás közé lell zárni.
A tényleges kirajzolás mindig a stroke()
végrehajtásával történik meg.
Természetesen kitöltést is adhatunk a rajzi elemeknek, a fill()
metódus használatával.
A kitöltés színét, esetleg mintáját a fillStyle
tulajdonság értéke határozza meg, míg a vonalak színét a strokeStyle
... with(rajzCt) { beginPath(); rect(100,200,200,200); fillStyle="#ff8080"; strokeStyle="red"; fill(); stroke(); beginPath(); moveTo(100,200); lineTo(200,60); lineTo(300,200); fillStyle="#80ff80"; strokeStyle="green"; fill(); stroke(); } ...2. példa: egyszerű vonalas rajz, színekkel, kitöltéssel.
Lehetőségünk van "lyukas" poligonokat is létrehozni. Ehhez arra kell ügyelnünk, hogy a belső határokat a külsőhöz képest ellentétes körüljárási iránnyal definiáljuk.
(A rect()
által rajzolt téglalap körüljárási iránya óramutató szerinti.)
... beginPath(); rect(100,200,200,200); moveTo(110,210);lineTo(110,300);lineTo(195,300);lineTo(195,210);lineTo(110,210); moveTo(205,390);lineTo(290,390);lineTo(290,210);lineTo(205,210);lineTo(205,390); fillStyle="#ff8080"; strokeStyle="red"; fill(); stroke(); ...2/a. példa: "lyukas" poligon kitöltéssel.
Ha fájlból szeretnénk egy raszteres képet a vászonra helyezni, először be kell azt tölrtnünk a memóriába, mint Image()
objektumot.
Az objektum onload
eseménykezelőjében kell a kép tényleges kirajzolását elvégezni.
Ez azért van, mert addig nem tudjuk megjeleníteni a képet, amíg be nem töltődött, viszont a képbetöltés aszinkron folyamat, tehát a programkód futása nem ál meg a töltés befejeztéig.
... // bitkép létrehozása var kep=new Image(); // betöltés után jelenítsük majd meg kep.onload=function() { with(rajzCt) { drawImage(kep,105,205,190,190); // a kép elé rajzoljuk a házfalat az ablakkal-ajtóval beginPath(); rect(100,200,200,200); moveTo(110,210);lineTo(110,300);lineTo(195,300);lineTo(195,210);lineTo(110,210); moveTo(205,390);lineTo(290,390);lineTo(290,210);lineTo(205,210);lineTo(205,390); fillStyle="#ff8080"; strokeStyle="red"; fill(); stroke(); // tető beginPath(); moveTo(100,200); lineTo(200,60); lineTo(300,200); fillStyle="#80ff80"; strokeStyle="green"; fill(); stroke(); } } kep.src="tj.jpg"; ...3. példa: kép betöltése fájlból.
A Canvas pixeleihez közvetlenül is hozzáférhetünk. A vászon egy téglalap alakú részének képadatai kinyerhetők a getImageData(x0,y0,w,h)
metódussal.
Ennek eredménye egy ImageData
objektum, melynek data
adattagja egy egydimenziós tömbben tartalmazza a pixelek adatait.
Minden pixelt 4 egymást követő érték reprezentál (R,G,B,A), így az i. sor j. pixelének adatai a data[(i*w+j)*4]
- data[(i*w+j)*4+3]
helyeken vannak.
ImageData objektumot üresen is létrehozhatunk a createImageData(w,h)
metódussal.
A putImageData(imageData,x0,y0)
segítségével pedig a Canvas megfelelő helyére rakhatunk egy ImageData objektumot.
Így pl. átmásolhatjuk a kép egyes részeit máshova, vagy a módosított képrészletet visszarajzolhatjuk a helyére. A következő példában a képet gombnyomásra "negativizálhatjuk":
minden pixel (R, G, B) értéke (255-R, 255-G, 255-B)-re változik.
... function negativ() // negatív kép létrehozása { var iData=rajzCt.getImageData(0,0,600,600); var l=iData.data.length; for(var i=0;i<l;i++) if (i%4!=3) iData.data[i]=255-iData.data[i]; rajzCt.putImageData(iData,0,0); } ...4. példa: pixelenkénti képmanipuláció.
x. példa: térkép rajzolás szövegfájl beolvasásával
y. példa: az előbbi térkép kiegészítése JSON formátumú adatok megjelenítésével
z. példa: Mandelbrot- és Julia-halmaz böngésző