M.: Canvas und Attribut vs. CSS

Mahlzeit,
hab mir mal <canvas> angesehen, weil ich mal Animationen im Browser testen wollte.

Nun hab ich folgendes Problem: Wenn ich <canvas width="250" height="250" id="speedo"></canvas>
schreibe, wird die gezeichnete Linie zentriert, wenn ich <canvas id="speedo"></canvas> schreibe und per CSS width und height angebe, dann nicht.

Ich gehe davon aus, dass es mit den Init-Werten zu tun hat, aber ich kommnicht dahinter, wo das Problem liegt.

Kann es aktuell nicht online stellen, da es im Framework läuft, deshalb ist das HTML auch nur ein Ausschnitt.

Grundsätzlich ist es ja nicht schlimm, wenn da ein paar Attribute drinstehen, aber es spricht gegen strikte Trennung von Inhalt und Design und ist bei Änderungen mehr Aufwand.

Getestet mit Chrome 27.0.1453.110 unter Debian. Wäre schön, wenn mir jemand das Problem verstehen hilft ;)

CSS-Code

  
canvas {  
	border: 1px solid red;  
}  
  
canvas#speedo {  
	width: 250px;  
	height: 250px;  
}  

JS (Aktuell wird ein Sekundenzeicger animiert, später soll die Geschwindigkeit angezeigt werden, die vom GPS kommt)

  
function speedo(oSpeedo)  
{  
	var width = document.getElementById('speedo').offsetWidth;  
	var height = document.getElementById('speedo').offsetHeight;  
  
	var objDate = new Date();  
	var intSek = objDate.getSeconds();  
	var cSpeedo = oSpeedo.getContext("2d");  
  
	cSpeedo.clearRect(0, 0, width, height);  
  
	cSpeedo.save();  
	cSpeedo.translate(width / 2, height / 2);  
  
	cSpeedo.save();  
	cSpeedo.rotate(intSek * Math.PI / 30);  
	cSpeedo.beginPath();  
	cSpeedo.moveTo(0, 10);  
	cSpeedo.lineTo(0, 0 - (width / 2));  
	cSpeedo.lineWidth = 2;  
	cSpeedo.strokeStyle = "#a00";  
	cSpeedo.stroke();  
	cSpeedo.restore();  
  
	cSpeedo.restore();  
  
	timer = window.setTimeout(function(){ speedo(oSpeedo);}, 1000);  
}  

HTML

  
<canvas width="250" height="250" id="speedo"></canvas>  
<!-- <canvas id="speedo"></canvas> -->  
  
<script type="text/javascript">  
window.onload = function(){  
	var oSpeedo = document.getElementById("speedo");  
  
	if(oSpeedo.getContext){  
		speedo(oSpeedo);  
	}  
}  
</script>  

  1. Meine Herren,

    Grundsätzlich ist es ja nicht schlimm, wenn da ein paar Attribute drinstehen, aber es spricht gegen strikte Trennung von Inhalt und Design und ist bei Änderungen mehr Aufwand.

    Dieser Fall bildet eine Ausnahme. Schau dir mal das Canvas-Element in der Konsole an (console.dir statt console.log). Dir wird auffallen, dass dort zwei verschiedene Arten von Attributen stehen, die beide etwas mit Höhe und Breite zu tun haben. Zum einen sind das height und width zum anderen sind das clientHeight und clientWidth (wenn mans genau nimmt, kommen noch offsetHeight und offsetWidht hinzu). clientHeight und clientWidth stehen jeweils auf 250. height steht auf 300 und width auf 150. Und genau da liegt der Knackpunkt. Diese beiden Attribute geben nämlichen die Dimensionen des verwendeten Koordinatensystems innerhalb des Canvas' an. Und diese beiden Eigenschaften stimmen respektiv mit den in den HTML-Attribute width und height angebenen Werten überein. 300 und 150 sind Standardwerte, die benutzt werden, wenn die Attribute fehlen sollten.

    Die Werte dienen folglich nicht ausschließlich der Präsentation (auch wenn sie als Standard herangezogen werden, wenn durch CSS keine anderen Angaben spezifiziert sind), sondern vorrangig um das Koordinatensystem festzulegen. Siehe Spezifikation.

    Es gibt übrigens auch noch andere Ausnahmen, wo die Attribute width und height zu dulden und sogar nützlich sind. Bei Bildern dienen sie zum Beispiel der Rendering-Engine als Hilfestellung, um Umherspringen beim Seitenaufbau zu vermeiden.

    1. Danke für die Erklärung. Das leuchtet ein, auch wenns mich nicht glücklich macht ;)
      Ich lege die Grösse dann einfach per Attribut fest. Dank Smarty kann die Grösse ja trotzdem aus der Datenbank kommen ;)

      Schon wieder was gelernt heute :)