Simuliertes 3D-Objekt, mit Canvas und JavaScript realisiert
Immer weniger Surfer können Java-Applets anzeigen, dafür wurde der Support der Browser für Canvas immer besser. So als Versuch habe ich mein erstes Applet mit Canvas und JavaScript neu implementiert.
Wenn Sie mit der Maus über das Objekt fahren, dreht es sich um seinen Mittelpunkt. Auf dem Tablet funktioniert das nicht, und deshalb gibt es jetzt eine bessere Version.
Das Objekt wird nicht etwa durch WebGL dargestellt, sondern verwendet den "Painters Algorithm". Dabei werden weiter entfernte Flächen zuerst gezeichnet, und dann alle anderen auf der Z-Achse bis zum Betrachter darüber.
Der Code sieht vereinfacht so aus:
// Ecken definieren var points = [ { x: 1, y: 1, z: 1 }, { x: 1, y: 1, z:-1 }, { x:-1, y: 1, z:-1 }, { x:-1, y: 1, z: 1 }, { x: 1, y:-1, z: 1 }, { x: 1, y:-1, z:-1 }, { x:-1, y:-1, z:-1 }, { x:-1, y:-1, z: 1 } ] ; // Flächen definieren var surfaces = [ { p0: 3, p1: 2, p2: 6, p3: 7, color: "#FF0000" }, { p0: 0, p1: 6, p2: 5, p3: 3, color: "#0000FF" }, { p0: 0, p1: 1, p2: 5, p3: 4, color: "#FF0000" }, { p0: 0, p1: 4, p2: 7, p3: 3, color: "#FFFFFF" } ] ; // Hilfsvariablen var canvas, ctx, sinalpha, cosalpha, sinbeta, cosbeta ; // X-Koordinate der Projektion berechnen function px( point ) { return (cosalpha * point.x - sinalpha * point.y) * 100 + 200 ; } // Y-Koordinate der Projektion berechnen function py( point ) { return (cosbeta * point.z - sinbeta * (cosalpha * point.y + sinalpha * point.x)) * 100 + 200 ; } // Eine Fläche zeichnen function drawsurface( s ) { ctx.beginPath() ; ctx.moveTo( px(points[s.p0]), py(points[s.p0]) ) ; ctx.lineTo( px(points[s.p1]), py(points[s.p1]) ) ; ctx.lineTo( px(points[s.p2]), py(points[s.p2]) ) ; ctx.lineTo( px(points[s.p3]), py(points[s.p3]) ) ; ctx.closePath() ; ctx.fillStyle = s.color ; ctx.fill() ; } // Körper zeichnen. alpha und beta sind die Drehwinkel function draw( alpha, beta ) { // Hilfsvariablen berechnen sinalpha = Math.sin( alpha ) ; cosalpha = Math.cos( alpha ) ; sinbeta = Math.sin( beta ) ; cosbeta = Math.cos( beta ) ; // Hintergrund löschen ctx.clearRect( 0, 0, canvas.width, canvas.height ) ; // Bodenfläche zuerst zeichnen wenn der Körper nach vorne gekippt ist if( beta <= 0 ) drawsurface( surfaces[3] ) ; // Reihenfolge der Flächen wenn der Körper nach rechts gedreht ist if( alpha >= 0 ) { drawsurface( surfaces[0] ) ; drawsurface( surfaces[1] ) ; drawsurface( surfaces[2] ) ; } else { drawsurface( surfaces[2] ) ; drawsurface( surfaces[1] ) ; drawsurface( surfaces[0] ) ; } // Bodenfläche zuletzt zeichnen wenn der Körper nach hinten gekippt ist if( beta > 0 ) drawsurface( surfaces[3] ) ; }
Die Mittelfläche war übrigens nicht so geplant, sondern entstand durch einen Zählfehler bei der Applet-Version. Was dabei herauskam, gefiehl mir aber besser als meine ursprüngliche Idee ;-)