Ich arbeite gerade an einer Sport App und muss hier verschiedene Daten visualisieren. Dank zahlreicher JavaScript Bibliotheken gibt es eine große Auswahl für diese Aufgabe. Fast alle diese Bibliotheken benutzen das canvas Element zum Zeichnen.

Dabei ist mir ein Problem aufgefallen das mir nicht bewußt war. In der Bibliothek Gauge.js gibt es ein schönes Anzeigecontrol das einen Wert mit einer Animation ausgibt. Das schöne ist, es hat keine Abhängigkeiten zu anderen Bibliotheken und zeichnet schön sauber mit requestAnimationFrame. Das Control sieht super aus und hat viele Einstellmöglichkeiten. Der Beispielcode der Webseite entsprechend hier angegeben

Beispiel Gauge.js

<script src="gauge.js"></script>
<script>

document.addEventListener("DOMContentLoaded", function() {

var opts = {
lines: 12, // The number of lines to draw
angle: 0.15, // The length of each line
lineWidth: 0.44, // The line thickness
pointer: {
length: 0.9, // The radius of the inner circle
strokeWidth: 0.035 // The rotation offset
},
colorStart: '#6FADCF', // Colors
colorStop: '#8FC0DA', // just experiment with them
strokeColor: '#E0E0E0' // to see which ones work best for you
};
var target = document.getElementById('target'); // your canvas element
var gauge = new Gauge(target).setOptions(opts); // create sexy gauge!

gauge.setTextField(document.getElementById("output"));
gauge.maxValue = 150; // set max gauge value
gauge.animationSpeed = 64; // set animation speed (32 is default value)
gauge.set(110);
})

</script>

Beim Einbinden habe ich den Canvas nicht eine größe über die Element Attribute mitgegeben, sondern dieses mal mit CSS die Größe verändert.

#target {
width: 600px;
height: 300px;
}

Und schwups, sieht das Scheiße aus.

canvas-with-css-scale

Der Canvas sieht wie eine skalierte Grafik aus. Mein erster Gedanke: “CSS scheint wohl nach dem Zeichnen zu skalieren”. Das gleiche mit Attributswerten ausprobiert

target.width = 600;
target.height = 300;

und tatsächlich. Jetzt sieht es wieder scharf gezeichnet aus.

canvas-with-attribute-scale

Eine gute Erklärung habe ich schließlich auf StackOverflow gefunden.

Warum gibt es eigentlich kein Embed Widget von StackOverflow um Antworten zu integrieren?

CSS3 Media Query Listeners

Grundsätzlich werde ich das Canvas Element nun per Attribut setzen, bzw. das im JavaScript Code machen. Das ist in diesem Falle ärgerlich weil die direkte Unterstützung von CSS3 Media Queries für meine App nur über einen Listener gelöst werden kann. Die deklarative Einstellung wird nicht zu dem gewünschten Ergebnis führen.