screenglow
screenglow

Reputation: 1886

Why is my canvas line so small and disoriented?

In my very simple code example below, I am trying to draw a box, 10 pixels in from the margin all the way around the outside of a canvas. Despite getting what seem like legit values from the screen extends of the browser window, I am only getting an L-shaped line, which seems really odd. My code seems very straight forward. So 2 questions:

<html>
<head></head>
<body>
<p id="X">X:</p>
<p id="Y">Y:</p>
<!--<form>
Timeline Item: <input type="text" name="item"><br>
Timeline Date: <input type="date" name="date"><br>
</form>-->
<canvas id="DemoCanvas" width=100% height=100%></canvas>  

<script>  

var canvas = document.getElementById('DemoCanvas');
var xoutput = document.getElementById('X');
var youtput = document.getElementById('Y');


// Always check for properties and methods, to make sure your code doesn't break in other browsers.
if (canvas.getContext) 
 {
 	var margin = 10;

 	var startx = margin;
 	var starty = margin;

 	var endx = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) - margin;
	var endy = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) - margin;

	xoutput.innerHTML = endx;
	youtput.innerHTML = endy-margin;

 	var context = canvas.getContext('2d');

  	context.beginPath(); 

  	context.moveTo(startx,starty);
  	context.lineTo(endx,starty);
	context.lineTo(endx,endy);
 	context.lineTo(startx,endy);
  	context.lineTo(startx,starty);
  
 	context.stroke();
 }
</script>  

</body>
</html>

Here's the result which you can clearly see is both way too small and not a box at all:

Resulting not-a-box

Upvotes: 0

Views: 86

Answers (2)

user2267175
user2267175

Reputation: 593

Because you are using window / document width & height, e.g. the entire webpage, so the lines goes outside of the canvas.

you should instead use the canvas element's width & height.

var canvas = document.getElementById('DemoCanvas');
var xoutput = document.getElementById('X');
var youtput = document.getElementById('Y');


// Always check for properties and methods, to make sure your code doesn't break in other browsers.
if (canvas.getContext) 
 {
 	var margin = 10;

 	var startx = margin;
 	var starty = margin;

 	var endx = canvas.clientWidth - margin;
	var endy = canvas.clientHeight - margin;

	xoutput.innerHTML = endx;
	youtput.innerHTML = endy-margin;

 	var context = canvas.getContext('2d');

  	context.beginPath(); 

  	context.moveTo(startx,starty);
  	context.lineTo(endx,starty);
	context.lineTo(endx,endy);
 	context.lineTo(startx,endy);
  	context.lineTo(startx,starty);
  
 	context.stroke();
 }
<p id="X">X:</p>
<p id="Y">Y:</p>
<!--<form>
Timeline Item: <input type="text" name="item"><br>
Timeline Date: <input type="date" name="date"><br>
</form>-->
<canvas id="DemoCanvas" width=100 height=100></canvas>  

To achieve "fullscreen", something you can do is to use a parent element or the body tag and then "copy" it's width & height to the canvas afterwards. Note that i use vh & vw instead of % to avoid any stretching issues, etc.

var canvas = document.getElementById('DemoCanvas');
var xoutput = document.getElementById('X');
var youtput = document.getElementById('Y');

updateCanvasSize();

function updateCanvasSize(){
  canvas.width = bodySim.clientWidth;
  canvas.height = bodySim.clientHeight;
  
  draw();
  }
 
function draw(){
 if (canvas.getContext) 
 {
 	var margin = 10;

 	var startx = margin;
 	var starty = margin;

 	var endx = canvas.clientWidth - margin;
	var endy = canvas.clientHeight - margin;

	xoutput.innerHTML = endx;
	youtput.innerHTML = endy-margin;

 	var context = canvas.getContext('2d');

  	context.beginPath(); 

  	context.moveTo(startx,starty);
  	context.lineTo(endx,starty);
	context.lineTo(endx,endy);
 	context.lineTo(startx,endy);
  	context.lineTo(startx,starty);
  
 	context.stroke();
 }
} //end of draw
#bodySim {
  width: 100vw;
  height: 100vh;
}
<p id="X">X:</p>
<p id="Y">Y:</p>
<!--<form>
Timeline Item: <input type="text" name="item"><br>
Timeline Date: <input type="date" name="date"><br>
</form>-->
<div id="bodySim">
<canvas id="DemoCanvas" ></canvas>
</div>

Upvotes: 1

Schlaus
Schlaus

Reputation: 19252

Your problem stems from the common misunderstanding of the canvas' height and width properties. You're giving the values as percents, but that wont work. From MDN:

HTMLCanvasElement.height Is a positive integer reflecting the height HTML attribute of the element interpreted in CSS pixels. When the attribute is not specified, or if it is set to an invalid value, like a negative, the default value of 150 is used.

So you should use plain integers instead. If you need a dynamic size, you can use javascript to update the values.

<html>
<head></head>
<body>
<p id="X">X:</p>
<p id="Y">Y:</p>
<!--<form>
Timeline Item: <input type="text" name="item"><br>
Timeline Date: <input type="date" name="date"><br>
</form>-->
<canvas id="DemoCanvas" width="628" height="200"></canvas>  

<script>  

var canvas = document.getElementById('DemoCanvas');
var xoutput = document.getElementById('X');
var youtput = document.getElementById('Y');


// Always check for properties and methods, to make sure your code doesn't break in other browsers.
if (canvas.getContext) 
 {
 	var margin = 10;

 	var startx = margin;
 	var starty = margin;

 	var endx = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) - margin;
	var endy = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) - margin;

	xoutput.innerHTML = endx;
	youtput.innerHTML = endy-margin;

 	var context = canvas.getContext('2d');

  	context.beginPath(); 

  	context.moveTo(startx,starty);
  	context.lineTo(endx,starty);
	context.lineTo(endx,endy);
 	context.lineTo(startx,endy);
  	context.lineTo(startx,starty);
  
 	context.stroke();
 }
</script>  

</body>
</html>

Upvotes: 1

Related Questions