Blog der Heimetli Software AG

Lissajous-Figur in SVG

Dieser Post entstand weil zwei neue Erkenntnisse zusammenkamen:

  • SVG kann recht einfach sein. Schon aus einem einzelnen path-Element kann ein ganzes Bild entstehen.
  • Auf meinem Disk liegt ein JavaScript-Interpreter für die Kommandozeile. Und zwar dort wo ich es nie erwartet hätte: im Java-Directory!

JavaScript in Java

Ich hatte irgendwann gelesen, dass das möglich sein soll, aber dem Thema keine weitere Beachtung geschenkt. Mehr oder weniger zufällig bin ich dann auf der Seite von Oracle über Nashorn gelandet und habe darin herumgestöbert.

So richtig gepackt hat es mich aber erst, als ich die Kommandozeilenversion entdeckte: jjs. Ich hab's auch gleich probiert, und es funktioniert tatsächlich.

Anscheinend kann man recht wilde Sachen damit machen, aber so weit muss man gar nicht gehen. Ganz normales JavaScript mit ein paar print-Statements liefert schon interessante Ergebnisse.

Weil ich gerade das Lissajous-Fieber habe, habe ich den Code aus der Seite kopiert, und so abgeändert dass SVG ausgegeben wird.

SVG

SVG ist zwar XML, aber was da abgeht hat nur wenig mit XML zu tun. Ein path-Element ist ein regelkonformes XML-Element, aber alle Graphik-Anweisungen stehen im d-Attribut! Diese Art der Darstellung passt mir eigentlich gar nicht, und deshalb habe ich es auch lange ignoriert.

Kürzlich bin ich aber auf ein Bild gestossen das aus einem einzigen path-Element in einem svg-Element bestand. Das hat mich dazu animiert, wieder mal mit SVG herumzuspielen.

Eine Lissajous-Figur in SVG

Der Code für den Canvas existierte schon, und die Anpassungen für die Ausgabe von SVG erwiesen sich als recht einfach: moveTo wird zu "M" und lineTo zu "L". Dazu ein svg-Element und schon hat man ein SVG-Bild.

Ein XML-Prolog wird nicht ausgegeben, weil schon von Anfang an klar war dass die Darstellung auf eine Webseite soll.

/******************************************************************************/
/*                                                                            */
/*                                                      FILE: svglissajous.js */
/*                                                                            */
/*  Writes the SVG for a Lissajous Figure to standard output                  */
/*  ========================================================                  */
/*                                                                            */
/*  V1.0  18-JUL-2015  Te       http://www.heimetli.ch                        */
/*                                                                            */
/******************************************************************************/

// Computes the value for x at a given angle
function fx( angle )
{
   return 90 + 58 * (Math.sin(angle) -  0.25 * Math.sin(5*angle)- 0.5 * Math.sin(15*angle)) ;  
}

// Computes the value for y at a given angle
function fy( angle )
{
   return 120 + 58 * (Math.cos(angle)- 0.75 *Math.cos(5*angle)- 0.5 *Math.cos(15*angle)) ;  
}

// Draws the figure
function draw()
{
   var angle = 0 ;

   // Start the svg element
   print( "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 180 240\">" ) ;

   // Start a path
   print( "<path d=\"M" + fx(angle) + " " + fy(angle) ) ;
   angle += 0.005 ;

   // First point, needs 'L'
   print( "L" + fx(angle) + " " + fy(angle) ) ;
   angle += 0.005 ;

   // Angle is in radian, 2 * PI is a full circle
   while( angle < 2 * Math.PI )
   { 
      // Add a point to the path
      print( fx(angle) + " " + fy(angle) ) ;
      angle += 0.005 ;
   }

   // End the path
   print( "z\" style=\"stroke:#000000; fill:#FF0000;\" fill-rule=\"evenodd\"/>" ) ;

   // End the svg element
   print( "</svg>" ) ;
}

// Start drawing
draw() ;  

Die Figur erzeugen

Dank jjs ist es wirklich einfach:

jjs svglissajous.js > lissajous.svg

Wenn es eine Option gibt um den Output direkt in ein File zu schreiben, dann habe ich sie auf jeden Fall nicht gefunden...

Und so sieht es aus:

Sie können svglissajous.js und lissajous.svg herunterladen und selber damit spielen.

Nachtrag 23.7.2015: Internet Explorer

Ich hatte wirklich gedacht, dass ein aktueller IE sich wie alle anderen Browser verhält, aber weit gefehlt: Im IE skaliert das Bild nicht.

Eine Google-Suche bestätigte, dass das nicht ein Fehler in meinem SVG ist, sondern ein "Feature" vom IE. Allerdings muss man festhalten, dass der Standard diesen Punkt nicht definiert, so dass man nicht von einem IE-Fehler sprechen kann.

Trotzdem ist es nicht in Ordnung, dass sich der IE anders als alle anderen Browser verhält :-(

Naürlich gibt es auch dutzende von Hacks, wie man die IEs dazu bringen kann, ein SVG gleich wie andere Browser darzustellen. Aber ich mag nun mal keine Hacks, und deshalb sehen IE-Nutzer nur eine Minimal-Version der Graphik.