Playing with SVG: Charts

english preferred


Meinereiner hat einen guten Bürostuhl und bewegt sich zu wenig. Das iPhone habe ich immer in der Hosentasche. Vor zwei Jahren begann ich, die täglichen Schritte aufzeichnen zu lassen. Die Tageswerte trage ich am nächsten Morgen in mein 4D-Büro ein.

Ich bin mit dem GRAPH-Befehl in V14 nicht zufrieden. Die Angebote in die WebArea zu charten waren nicht überzeugend. Jetzt mache ich mir die Charts selber. Ich organisiere mir die Daten vorab in Arrays und setze dann die Arrays in SVGs um. Zu diesem Zweck kann ich die 4D SVG-Komponente nur empfehlen.

Hier stelle ich die Schritte von fast 800 Tagen als Einzelwerte und die Wochenschnitte chronologisch dar.

Das Verfahren ist im Prinzip einfach. Zuerst wird ein neues SVG erzeugt in den Maßen des Zielobjektes.
svgRef:=SVG_New ($right_L$left_L;$unten_L$top_L)
Danach wird für jeden Datensatz ein Kreis gezeichnet
$objectRef:=SVG_New_circle ($svgRef;$t_x_L{$i};$t_y_R{$i};2;“none“;$colorname;1)
Schließlich über alle Einzelpunkte die Wochenmittel als Polygonzug gelegt.
$polyRef:=SVG_New_polyline_by_arrays ($svgRef;->$t_WocheX_L;->$t_WocheY_R;“blue“;“none“;1)
Zum Schluß das SVG als Bild exportiert
GraphPict:=SVG_Export_to_picture ($svgRef;1) // 1 = mit data-source
und der Speicher aufgeräumt
SVG_CLEAR ($svgRef)

Das Chart gefiel mir schon besser. Aber der Polygonzug sollte sich besser abheben, über den Einzelwerten schweben. Auch einfacher als gedacht. Erst einen Filter definieren
$shadowFilter:=SVG_Define_filter ($svgRef;“shadow“)
unschärfen
SVG_Filter_Blur ($shadowFilter;4)
und versetzen.
SVG_Filter_Offset ($shadowFilter;4)
Dann den Filter auf den Polygonzug anwenden
SVG_SET_FILTER ($polyRef;“shadow“)

Mit diesem Chart bin ich zufrieden.

Doch gibt es einen Zusammenhang mit den Jahreszeiten? Also die gleichen Daten noch einmal über die Kalenderwoche zeichnen und für jedes Jahr einen neuen Polygonzug starten:

Was sehe ich:

  • 2013 habe ich mit einem iPhone 4 aufgezeichnet, ab 2014 auf einem 5s mit Motion-Processor.
  • Die guten Vorsätze für 2015 scheinen zu wirken.
  • iPhone liegen lassen, verschlechtert den Durchschnitt.

Anstatt den Ausschnitt zu definieren und den Skalierungsfaktor zu ermitteln, habe ich alle Koordinaten im Array auf die Maße der Bildvariablen umgerechnet. Es war einfacher. Außerdem zeichne ich die Tage mit mehr als 12.500 Schritte außerhalb des sichtbaren, sonst sollte ich eine zweite Y-Achse für die Wochenmittel verwenden.

4D ist so schnell, das ich während des Resize-Events die komplette Graphik neuzeichne. Das ist viel weniger Aufwand als die Geometrie zu aktualisieren.

Ich habe allen SVG-Elementen IDs zugewiesen, dann erkenne ich die Elemente in Sketch sofort, falls ich mal Sichern als… SVG verwende und extern überprüfe:
SVG_SET_ID ($polyRef;$id)

Ausgelassen habe ich das Zeichnen der Linien und die Beschriftungen. Das funktioniert vergleichbar dem Zeichnen des Kreises.


lieber auf deutsch

I love my office-chair. Downside, too much sitting and not enough walking. My iPhone is always in my pocket. So I started to record my daily moves two years ago. Next morning I update my 4D-office-software with yesterdays sum of moves.

The 4D GRAPH-command of V14 is sub-par for my needs. There are options to chart into a 4D webarea but I wasn’t convinced. Now I do the charting myself. I start with selection to array and build SVGs from the arrays. I use the 4D SVG-component which makes the whole process even easier.

This graph displays nearly 800 days of data-points. Every single value chronological plus a weekly average.

It comes down to this simple process. First create a new SVG fitted to the size of the display-variable.
svgRef:=SVG_New ($right_L$left_L;$unten_L$top_L)
Then draw a circle for every data-point
$objectRef:=SVG_New_circle ($svgRef;$t_x_L{$i};$t_y_R{$i};2;“none“;$colorname;1)
Overlay with a polyline of weekly averages.
$polyRef:=SVG_New_polyline_by_arrays ($svgRef;->$t_WocheX_L;->$t_WocheY_R;“blue“;“none“;1)
Finally export into a picture
GraphPict:=SVG_Export_to_picture ($svgRef;1) // 1 = mit data-source
and clear the memory
SVG_CLEAR ($svgRef)

That graph looks nice. The polyline could be enhanced when displayed as laying above the data-points. Not a big deal. First define a filter
$shadowFilter:=SVG_Define_filter ($svgRef;“shadow“)
set unsharpness
SVG_Filter_Blur ($shadowFilter;4)
and offset of filter.
SVG_Filter_Offset ($shadowFilter;4)
Finally apply the filter to the polyline
SVG_SET_FILTER ($polyRef;“shadow“)

Now the graph looks even nicer.

Do I move differently according to season? Reusing the same data and plotting the weekly average for every week of the year for the three years:

What does that tell me:

  • 2013 was recorded with an iPhone 4, early 2014 I changed for a 5s with motion-CPU.
  • my resolutions made for 2015 seem to work.
  • iPhone not in my pocket is bad for the weekly average.

I could have used unmodified data and set the scale and clipped later. Seemed more obvious to me to calculate according to the size of the picture-var myself. There are days with more than 12,5oo steps. I drew them outside of the visible area to avoid a second y-axis to plot the weekly averages.

4D is really fast nowadays, so I recalculate and redraw a complete new graph while resizing the form. Seemed much easier then updating the geometry of the graph.

Every SVG-element gets an ID:
SVG_SET_ID ($polyRef;$id)
Which makes things recognizable when Saving as … SVG and checking or enhancing with Sketch.

I omitted the drawing of lines and text to make the graph readable. This is similar to drawing the circle.