How do I make a Canvas HTML picture bigger without losing resolution? - javascript

My canvas size is 300x150. I don't want to set the measurements any bigger than this because I'd like it fit on mobile phones as well. But i'd like it to scale up on bigger phones, ipads and laptops without losing resolution. The resolution on my canvas pictures have generally been bad and when it scales up it typically gets even worse. Not sure how to solve this problem. Thanks.
https://jsfiddle.net/uwakcgv0/
Here's the HTML:
<canvas width="300" height="150" id="myCanvas"></canvas>
Here's the Javascript:
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, 300, 150);
ctx.beginPath();
ctx.moveTo(20, 20);
ctx.lineTo(20, 130);
ctx.lineTo(130, 130);
ctx.stroke();
ctx.fillText("y",18,15);
ctx.fillText("x",135,132);

Increase the canvas size by any factor and then scale the canvas by the same factor (using ctx.scale()) to get the desired result.
const SCALING_FACTOR = 2;
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.canvas.width = SCALING_FACTOR * canvas.width;
ctx.canvas.height = SCALING_FACTOR * canvas.height;
ctx.scale(SCALING_FACTOR, SCALING_FACTOR);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(20, 20);
ctx.lineTo(20, 130);
ctx.lineTo(130, 130);
ctx.stroke();
ctx.fillText("y", 18, 15);
ctx.fillText("x", 135, 132);
<canvas width="300" height="150" id="myCanvas"></canvas>

Related

Change canvas width and height without losing the current draw

I'm creating a pixel art app and when I want to save the image from the canvas the image is so small, so it seems pixelated when I want to resize it.
I want to resize it to bigger dimensions, but I don't know how.
This is the code example:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.rect(0, 0, 50, 50);
ctx.fillStyle = 'red';
ctx.fill();
document.write('<img style="width:300px;" src="'+c.toDataURL("image/png")+'"/>');
// This is an image with dimensions 108x108px and it seems very bad when i resize it to 300x300px
// I want to download the canvas image with more resolution
<canvas id="myCanvas" width="108" height="108" style="width: 300px; height:300px;">
</canvas>
you can create a canvas and put the imageData in it.
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.rect(0, 0, 25, 25);
ctx.fillStyle = 'red';
ctx.fill();
ctx.beginPath();
ctx.rect(0, 25, 25, 25);
ctx.fillStyle = 'yellow';
ctx.fill();
ctx.beginPath();
ctx.rect(25, 0, 25, 25);
ctx.fillStyle = 'blue';
ctx.fill();
ctx.beginPath();
ctx.rect(25, 25, 25, 25);
ctx.fillStyle = 'green';
ctx.fill();
var c2 = document.createElement("canvas");
c2.width = 50;
c2.height = 50;
var ctx2 = c2.getContext("2d");
var imageData = ctx.getImageData(0, 0, 50, 50);
ctx2.putImageData(imageData, 0, 0);
document.write('<img style="width:300px;" src="' + c2.toDataURL("image/png") + '"/>');

How to solve problems with odd numbers as HTML-canvas size?

I'm working with the HTML-canvas-element.
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.fillStyle = "#FF0000";
ctx.rect(0, 0, canvas.width / 3, canvas.height / 3);
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.fillStyle = "#FF0000";
ctx.rect(canvas.width / 3, 0, canvas.width / 3, canvas.height / 3);
ctx.fill();
ctx.closePath();
<canvas id="c" width="541" height="541"></canvas>
The problem: When I choose an odd number (in this case the prime number 541) as canvas size and draw a rectangle on it (size: 1/3 of the whole canvas).
But this is the result:
zoomed in:
As you can see: There is an unwanted line in the between the 2 rectangles. How can I fix this problem?
Rounding the values with Math.floor(), Math.round() and Math.ceil() is (probably) not an option because the sum of the widths of the 3 rectangles must be equal to the width of the canvas.
Looks like you are using a HiDPI (High DPI, Retina) mode (with OS-level zoom of more than 100%) while your canvas approach is not HiDPI-compatible.
The solution is to increase the values of the CANVAS element’s width and height HTML attributes (or the element’s DOM properties) proportionally with window.devicePixelRatio while setting its corresponding CSS properties to what you current size is. Then your canvas will be HiDPI compatible and blur-free. That’s what I used in my web demo of nonblurry integer-ratio scaling:
var pixelRatio = window.devicePixelRatio;
canvas.width = 541 * pixelRatio;
canvas.height = 541 * pixelRatio;
canvas.style.width = '' + 541 + 'px';
canvas.style.height = '' + 541 + 'px';
An alternative approach is to use the scale() method of context object instead of setting CSS size. That’s what Paul Lewis from HTML5Rocks recommends:
var pixelRatio = window.devicePixelRatio;
canvas.width = 541 * pixelRatio;
canvas.height = 541 * pixelRatio;
canvas.getContext('2d').scale(pixelRatio, pixelRatio);
Works fine if you use the style tag or a css file
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.fillStyle = "#FF0000";
ctx.rect(0, 0, canvas.width / 3, canvas.height / 3);
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.fillStyle = "#FF0000";
ctx.rect(canvas.width / 3, 0, canvas.width / 3, canvas.height / 3);
ctx.fill();
ctx.closePath();
.canvas {
width: 541px;
height: 541px;
}
<canvas id="c" class="canvas"></canvas>
Not sure if you like this solution but you could use Math.floor() only on x2
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.fillStyle = "#FF0000";
ctx.rect(0, 0, canvas.width / 3, canvas.height / 3);
ctx.fill();
ctx.closePath();
// use here to make sure that the start position of the secound rect is right
var x2 = Math.floor(canvas.width / 3);
ctx.beginPath();
ctx.fillStyle = "#FF0000";
ctx.rect(x2, 0, canvas.width / 3, canvas.height / 3);
ctx.fill();
ctx.closePath();
<canvas id="c" width="541" height="541"></canvas>

canvas resolution not good

i am trying to draw a canvas line on div id "myCanvas" but problem is the line becomes very low resolution and its not shows smooth line. How can i increase that line resolution? And make it smooth line?
js:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.rect(0, 0, canvas.width, canvas.height);
var grd = context.createLinearGradient(100, 150, canvas.width, canvas.height);
grd.addColorStop(0, '#0132bf');
grd.addColorStop(1, '#ccd9ff');
context.fillStyle = grd;
context.fill();
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.beginPath();
context.lineTo(-10, 190);
context.bezierCurveTo(200, -100, 500, 200, 400, 150);
context.lineWidth = .9;
context.strokeStyle = '#ccd9ff';
context.stroke();
jsfiddle link
Try giving your canvas HTML element width and height attributes that fit your requirements, for example:
<canvas id="myCanvas" width="600" height="600">

How can I cut out a shape if it goes outside of a canvas with javascript?

I want to create a circle and cut out a part of it if it goes outside another shape.
For example, if half of the circle goes outside a square, cut out everything on the outside but not on the inside. Something like this snippet, except the part outside the square is hidden. I prefer to avoid masking it since this will go on top of another canvas, which covers the whole screen.
Code
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
ctx.rect(20,20,100,100);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.arc(70, 90, 60, 0, Math.PI * 2, false)
ctx.stroke();
ctx.restore();
<html>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
You can clip() the circle, like so;
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
ctx.rect(20,20,100,100);
ctx.stroke();
ctx.closePath();
ctx.clip(); // clip circle
ctx.beginPath();
ctx.arc(70, 90, 60, 0, Math.PI * 2, false)
ctx.stroke();
ctx.restore();
<html>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
This is the dimensions I've adjusted for cropping the outside part of sqaure
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
ctx.rect(20,20,100,100);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.arc(70, 90, 60, 10, -4*Math.PI * .05 , false)
ctx.stroke();
ctx.restore();
<html>
<body>
<canvas id="canvas"></canvas>
</body>
</html>

Canvas elements cut off at the

When I place a square on the canvas at 0,0 coords the top left is cut off:
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
context.strokeStyle = 'blue';
context.rect(0, 0, 200, 100);
context.fillStyle = 'yellow';
context.fill();
context.lineWidth = 7;
context.strokeStyle = 'black';
context.stroke();
<canvas id="c" width="500" height="500"></canvas>
Why is this?
It's because half the stroke is inside the rect.fill and the other half of the stroke is outside the rect.fill.
Kind of like css borders, you must account for them when sizing/positioning.
In canvas's case, the stroke is always half-in / half-out the object.

Categories