Dreidimensionale Animationen mit Hilfe der Library three.js
(EN google-translate)
(PL google-translate)
Es existieren verschiedene Libraries, die die Fähifkeiten von Javascript um die Möglichkeit 3D-Objekte darzustellen und zu animieren erweitern.
Exemplarisch soll hier die Library "Three" verwendet werden, da diese mit Hilfe der Methoden zu Generierung von Primitiven relativ einfach benutzt werden kann und auch eine gute Dokumentation (API) bietet.
Die komplette Library und die Dokumentation lassen sich über den Download offline verfügbar machen:
Zur Motivation: Einige interessante Beispiele von threejs.org
Die nachfolgenden Beispiele stehen auch alle im Ordner examples in master.zip zur Verfügung.
Erde: canvas_geometry_earth.html
Wüfel in 3D-Raum einfügen: canvas_interactive_voxelpainter.html
Kugelhaufen: webgl_postprocessing_msaa_unbiased.html
Molekülmodelle: css3d_molecules.html
Periodensystem anordnen: css3d_periodictable.html
Innenraum als Hintergrund mit spiegelnden Objekten darin: webgl_materials_cubemap_dynamic2.html
Meer: webgl_shaders_ocean.html
Seifenblasen: webgl_materials_shaders_fresnel.html
Vogelschwärme: canvas_geometry_birds.html
Stereoskopische Darstellung, z.B. zur Benutzeung mit einer VR-Brille, in die ein Smartphone eingesetzt wird: webgl_effects_stereo.html
Text darstellen:
Text2: webgl_geometry_text_earcut.html
Text3: webgl_geometry_text_pnltri.html
Stimmung / Wetter / Schatten
Nebel: webgl_postprocessing_godrays.html
Getting Started
Die nachfolgenden Beispiele funktionieren unter der Voraussetzung, dass unterhalb von htdocs auf dem (XAMPP-) Server der Inhalt des Ordners ..../three.js-master in techne/three abgelegt wurde.
Eine Einführung in Beispielen
Beispiel 1:
<html> <head lang="de"> <meta charset="iso-8859-1"> <script src="http://localhost/techne/three/build/three.js"></script> <script src="http://localhost/techne/three/examples/js/renderers/Projector.js"></script> <script src="http://localhost/techne/three/examples/js/renderers/CanvasRenderer.js"></script> <script src="http://localhost/techne/three/examples/js/libs/stats.min.js"></script> <script language:javascript> function KUBUSANIMATION() { const BREITE = 400; const HOEHE = 300; var kubus; var renderer,scene,camera; function erzeugeKubus() { var geometry = new THREE.BoxGeometry( 200, 200, 200 ); for ( var i = 0; i < geometry.faces.length; i += 2 ) { var hex = Math.random() * 0xffffff; geometry.faces[ i ].color.setHex( hex ); geometry.faces[ i + 1 ].color.setHex( hex ); } var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, overdraw: 0.5 } ); var cube = new THREE.Mesh( geometry, material ); cube.position.y = 150; return cube; } function erzeugeSceneInID(ID) { camera = new THREE.PerspectiveCamera( 70, BREITE / HOEHE, 1, 1000 ); camera.position.y = 150; camera.position.z = 500; scene = new THREE.Scene(); renderer = new THREE.CanvasRenderer(); renderer.setClearColor( 0xf0f0f0 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( BREITE, HOEHE ); document.getElementById(ID).appendChild( renderer.domElement ); return scene; } this.init = function() { scene = erzeugeSceneInID("container"); kubus = erzeugeKubus(); scene.add( kubus ); animate(); } function animate() { requestAnimationFrame( animate ); render(); } function render() { kubus.rotation.y+=0.02; renderer.render( scene, camera ); } } var kubusanimation = new KUBUSANIMATION(); </script> </head> <body> <input style="width:200px" type="button" id="snap" value="malen" onclick="javascript:kubusanimation.init()"/> <div id="container"></div> </body> </html>
Code 0-1: Quelltext zu obigem Beispiel.
Beispiel 2:
<html> <head lang="de"> <meta charset="iso-8859-1"> <script src="http://localhost/techne/three/build/three.js"></script> <script src="http://localhost/techne/three/examples/js/renderers/Projector.js"></script> <script src="http://localhost/techne/three/examples/js/renderers/CanvasRenderer.js"></script> <script src="http://localhost/techne/three/examples/js/libs/stats.min.js"></script> <script language:javascript> const SPEED = 10; let HEXA = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"]; var muenzwurf_x = 0.901; function muenzwurf() { muenzwurf_x = 3.92*muenzwurf_x*(1.0-muenzwurf_x); return (Math.round(muenzwurf_x*1000.0))%2; } function zufall(max) { var x = 0; var y = 0; var z = 0; for(var i=0;i<1000;i++) { x+=muenzwurf(); y+=muenzwurf(); z+=muenzwurf(); } return (x+y*103+z*911)%max; } //Farbbeispiele: http://html-color-codes.com/rgb.html function farbe(r,g,b) { return "#"+HEXA[Math.floor(r/16)]+HEXA[r%16]+HEXA[Math.floor(g/16)]+HEXA[g%16]+HEXA[Math.floor(b/16)]+HEXA[b%16]; } function KUGELANIMATION() { const BREITE = 400; const HOEHE = 300; var kugel = new Array(); var kugelxyz = new Array(); var renderer,scene,camera; var xz = [0,0]; var xzrot = [0,0]; var phi = 0.0; function dreheUmYachse(xz,phi,xzrot) { xzrot[0] = Math.cos(phi)*xz[0] + Math.sin(phi)*xz[1]; xzrot[1] = -Math.sin(phi)*xz[0] + Math.cos(phi)*xz[1]; } function erzeugeSphere(RADIUS,ROT,GRUEN,BLAU,X,Y,Z,rotX,rotY,rotZ) { var geometry = new THREE.SphereGeometry( RADIUS, 32, 32 ); var hex = Math.random() * 0xffffff; for ( var i = 0; i < geometry.faces.length; i += 2 ) { geometry.faces[ i ].color.setHex( hex ); geometry.faces[ i + 1 ].color.setHex( hex ); } var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, overdraw: 0.5 } ); var sphere = new THREE.Mesh( geometry, material ); sphere.position.x=X; sphere.position.y=Y; sphere.position.z=Z; sphere.rotation.x=rotX; sphere.rotation.y=rotY; sphere.rotation.z=rotZ; return sphere; } function erzeugeSceneInID(ID) { camera = new THREE.PerspectiveCamera( 70, BREITE / HOEHE, 1, 1000 ); camera.position.y = 150; camera.position.z = 500; scene = new THREE.Scene(); renderer = new THREE.CanvasRenderer(); renderer.setClearColor( 0xf0f0f0 ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( BREITE, HOEHE ); document.getElementById(ID).appendChild( renderer.domElement ); return scene; } function erzeugeZufallskugel() { var r = 10+zufall(20); var rot = zufall(256); var gruen = zufall(256); var blau = zufall(256); return erzeugeSphere(r,rot,gruen,blau,0,0,0,0,0,0); } this.init = function() { scene = erzeugeSceneInID("container_kugel"); for(var i=0;i<10;i++) { var kneu = erzeugeZufallskugel(); scene.add( kneu ); kugel[kugel.length]=kneu; var xyz = new Array(0,0,0); xyz[0] = zufall(200)-100; xyz[1] = zufall(200)-100 + 200; xyz[2] = zufall(200)-100; kugelxyz[kugelxyz.length] = xyz; } animate(); } function animate() { requestAnimationFrame( animate ); render(); } function render() { for(var i=0;i<5;i++) { var nr = zufall(kugel.length); var aktion = zufall(6); var xyz = kugelxyz[nr]; if(aktion==0) xyz[0]+=SPEED; else if(aktion==1) xyz[0]-=SPEED; else if(aktion==2) xyz[1]+=SPEED; else if(aktion==3) xyz[1]-=SPEED; else if(aktion==4) xyz[2]+=SPEED; else //if(aktion==5) xyz[2]-=SPEED; } for(var i=0;i<kugel.length;i++) { xz[0] = kugelxyz[i][0]; xz[1] = kugelxyz[i][2]; dreheUmYachse(xz,phi,xzrot); kugel[i].position.x = xzrot[0]; kugel[i].position.y = kugelxyz[i][1]; kugel[i].position.z = xzrot[1]; } renderer.render( scene, camera ); phi+=0.03; } } var kugelanimation = new KUGELANIMATION(); </script> </head> <body> <input style="width:200px" type="button" id="snap" value="malen" onclick="javascript:kugelanimation.init()"/> <div id="container_kugel"></div> </body> </html>
Code 0-1: Quelltext zu obigem Beispiel.
Reengineering
Zur Einarbeitung in three.js wurde das Beispiel canvas_geometry_cube.html so lange vereinfacht und umgeschrieben, bis der entstandene Code sich in dem Autor vertrauten Strukturen darbot.