JavaScript a böngészőben Szécsi László Vizualizáció és képszintézis
HTML head az oldal kitölti az ablakot <!DOCTYPE html> <html> <head> <title>UFO</title> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" type="text/css" href="css/style.css" /> </head> elemek stílusai itt lesznek folyt köv.
HTML body <body> <div id="container"> ez a cimke (tag) egy szakaszt definiál az oldalon ez egy HTML elem <body> <div id="container"> <canvas id="canvas"></canvas> <div id="overlay"></div> </div> <script src="js/keycodes.js"></script> <script src="js/Shader.js"></script> <script src="js/shaders/idle_vs.essl"></script> <script src="js/shaders/solid_fs.essl"></script> <script src="js/Program.js"></script> <script src="js/QuadGeometry.js"></script> <script src="js/Scene.js"></script> <script src="js/App.js"></script> </body> </html> vászon, erre rajzol a WebGL ezt a HTML szakaszt szeretnénk a vászon főlé rajzolni tartalmát a kódból módosítva könnyen jeleníthetünk meg szöveget JavaScript forráskód forrásfileok
CSS #container * { margin: 0; padding: 0; } #container { position: absolute; width: 100%; height: 100%; top: 0; left: 0; bottom: 0; right: 0; overflow: hidden; } töltse ki az oldalt nem kérünk scrollbart
CSS #canvas, #overlay #overlay { position: absolute; left: 10px; top: 10px; z-index: 20; } #canvas { width: 100%; height: 100%; top: 0; left: 0; bottom: 0; right: 0; z-index: 10; overflow: hidden; legyenek ugyanott felül a szöveg nem kérünk scrollbart
DOM Document Object Model HTML címkék hierarchiája mint szülő-gyerek kapcsolatban álló objektumok rendszere győkér: document firstChild nextSibling getElementById
Window window globális objektum ennek tulajdonsága minden globális a dokumentumot megjelenítő ablak absztrakciója > document.defaultView.document === document; < true
JavaScript belépési pont? valójában simán végrehajtódik az összes beágyazott script soronként, az elejétől kezdve változó- és függvénydefiníciók lefutnak de az oldal teljes betöltése után kezdődhet az érdemi kód futása
Oldal betöltése eseményfigyelő window.addEventListener('load', function() { const canvas = document.getElementById("canvas"); const overlay = document.getElementById("overlay"); overlay.innerHTML = "WebGL"; const app = new App(canvas, overlay); app.registerEventHandlers(); }); innentől ez az objektum intéz mindent
App konstruktor – gl context new App(c, o) üres objektumot hoz létre és ráhívja a konstruktort, ami tulajdonságokkal léthatja el. Így definálunk osztályt JS-ben. Az objektum később módosítható. App konstruktor – gl context const App = function(canvas, overlay) { this.canvas = canvas; this.overlay = overlay; this.gl = canvas.getContext("webgl2"); if (this.gl === null) { throw new Error( "Browser does not support WebGL2"); }
App konstruktor színtér létrehozás this.gl.pendingResources = {}; this.scene = new Scene(this.gl); this.resize(); }; ez az OpenGL kontextusba beszúrt tulajdonság hasznos lesz a betöltött erőforrások monitorozására object literal üres objektumhoz ez az objektum felel az erőforrások kezeléséért és kirajzolásáért rajzolási felbontás beállítása külön metódusban, mert ablakátméretezéskor is kell majd ugyanez
App.prototype az az objektum, ami az App konstruktorral létrehozott objektumok prototípusa lesz. Amikor egy objektumnak olyan metódusát hívjuk, ami nincs neki, a prototípus metódusa hívódik. Így az App példányok öröklik a prototípus metódusait. Így definiálunk metódusokat JS-ben. App resize App.prototype.resize = function() { this.canvas.width = this.canvas.clientWidth; this.canvas.height = this.canvas.clientHeight; this.gl.viewport(0, 0, this.canvas.width, this.canvas.height); }; rendering resolution canvas size az ablak melyik részébe rajzolunk
App registerEventHandlers App.prototype.registerEventHandlers = function() { window.addEventListener('resize', () => this.resize() ); window.requestAnimationFrame( () => this.update() ); }; Zárvány: nagyon gyakran használjuk A lokálisan definiált függvény hozzáfér a definiáló scope lokális változóihoz. Az arrow function szintakszissal a this ugyanaz, mint a befoglaló scope-ban. egyutasításos törzs, nem kell kapcsos zárójel üres paraméterlista frissíti a rajzolási felbontást és a viewportot váltsunk ki egy rajzolást ez a metódus fogja rajzolni a frame-et
App registerEventHandlers document.onkeydown = (event) => { //jshint unused:false }; document.onkeyup = (event) => { this.canvas.onmousedown = (event) => { this.canvas.onmousemove = (event) => { event.stopPropagation(); this.canvas.onmouseout = (event) => { this.canvas.onmouseup = (event) => { //jshint unused:false }; egy darab függvény- paraméter függvénytörzs (ezen a dián üres)
App update – update loop dolgok betöltés alatt App.prototype.update = function() { const pendingResourceNames = Object.keys(this.gl.pendingResources); if (pendingResourceNames.length === 0) { // animate and draw scene this.scene.update(this.gl); this.overlay.innerHTML = "Ready."; } else { this.overlay.innerHTML = "Loading: " + pendingResourceNames; } window.requestAnimationFrame( () => this.update() ); }; ha minden be van töltve, mehet a rajzolás ütemezzük be a következő frame-et ugyanezzel a kezelővel
Billentyűesemények feldolgozása nem a lenyomásra (typematic rate!) vagy felengedésre akarunk reagálni hanem minden frameben tudni, mi van épp lenyomva keysPressed objektum tualjdonságértékek true/false: le van-e nyomva tulajdonságnév a gomb neve az S billentyű neve "S" legyen, ha lehet... de az onkeydown eventjében keyCode van (S: 83???) keyCodes.js : globális keyboardMap tömb elemek a string nevek, pl. "S", "DELETE", "SPACE", "F1"
Billentyűesemények feldolgozása const App = function(canvas, overlay) { ... this.keysPressed = {}; ... document.onkeydown = (event) => { this.keysPressed[keyboardMap[event.keyCode]] = true; }; document.onkeyup = (event) => { this.keysPressed[keyboardMap[event.keyCode]] = false; }; ... } App.prototype.update = function() { ... this.scene.update(this.gl, this.keysPressed);