How to properly choose canvas width? - javascript

I am using the following code (in accordance with this answer) to have a responsive canvas:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
ctx.font = '52px verdana';
var text = 'Sample text';
var textWidth = ctx.measureText(text).width;
ctx.fillText(text, 50, 50);
canvas {
width: 100%;
height: auto;
}
<div class="container">
<div class="row">
<div class="col-md-12">
<canvas id="canvas" width="800">
Sorry, your browser doesn't support the <canvas> element.
</canvas>
</div>
</div>
</div>
It doesn't look well because the actual canvas element size is not 800, but 1140 (in my browser). Looks like I should detect the window size somehow and assign correct canvas size value. How should I do it? I am using the latest Twitter Bootstrap library.

Dont use css style
ctx.canvas.width = window.innerWidth || document.body.clientWidth;

Related

Canvas drawImage using the position of div on top of image

I have a div that is on top of the image. I have to get the image content which is inside the overlaying div and draw using canvas.
The problem I am facing is, I am not able to draw the correct image. I have to programmatically get the correct image below the div.
The image below shows the comparison of the original image and drawn image in canvas.
Below is my code which drawsImage by taking the coordinates of the div:
DrawImage() {
var canvas: any = document.getElementById("myCanvas");
var canvasRef = canvas.getBoundingClientRect();
var ctx = canvas.getContext("2d");
var imagemarker = document.getElementById("imagemarker");
var markerRef = imagemarker.getBoundingClientRect();
var img = document.getElementById("myimage");
ctx.drawImage(
img,
markerRef.left,
markerRef.top,
markerRef.width,
markerRef.height,
0,
0,
canvasRef.width,
canvasRef.height
);
}
And the html code to display image and canvas element:
<button (click)="DrawImage()">Draw</button>
<div id="imagemarkercontainer">
<div id="imagemarker"></div>
</div>
<img id="myimage" src="https://imgur.com/NWQo2xk.jpeg" width="300px"
height="250px">
<br>
<canvas id="myCanvas" width="300px" height="250px" style="border:1px
solid #d3d3d3;"></canvas>
I have attached a stackblitz example that shows the problem. https://stackblitz.com/edit/angular-4untgz?file=src%2Fapp%2Fapp.component.ts
How can I achieve this?
You need to take care of img bounding rect and also natural width & height of image.
As you are setting image width & height, get naturalWidth and calculate proportional width as below
var imgRef = img.getBoundingClientRect();
var nWidth = img.naturalWidth;
var nHeight = img.naturalHeight;
ctx.drawImage(
img,
( markerRef.left - imgRef.left) * nWidth /img.width ,
( markerRef.top -imgRef.top) * nHeight / img.height ,
markerRef.width * nWidth /img.width,
markerRef.height * nHeight / img.height ,
0,
0,
canvasRef.width,
canvasRef.height
);
Here is working code

drawImage - Resize and keep scale

I am trying to resize an image using drawImage but keep the scale. I have this so far...
window.onload = function() {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = document.getElementById("scream");
ctx.drawImage(img, 0, 0, 600, 428);
}
<p>Image to use:</p>
<img id="scream" width="400" height="300" src="http://lorempixel.com/1280/960/sports/" alt="The Scream">
<p>Canvas:</p>
<canvas id="myCanvas" width="428" height="600" style="border:2px solid black;">
Your browser does not support the HTML5 canvas tag.
</canvas>
I am trying to make the image fill the container to lose the white space at the bottom, if I put the exact dimensions in then it becomes stretched.
Does anyone have an example they can point me in the direction of?
First you need to find the aspect ratios of the image and the canvas. That is done by:
var canvasRatio = canvas.width / canvas.height,
imgRatio = img.width / img.height,
s = 1;
If a ratio is less than 1, then it is portrait, else if it is equal or higher than 1, it is (considered to be) landscape.
Then you need to compare those ratios like so:
//the image is »more portrait«
//to fully cover the canvas
//scale by width
if (imgRatio < canvasRatio) {
s = canvas.width / img.width;
//image has the same, or a »more landscape«
//ratio than the canvas
//to cover scale by height
} else {
s = canvas.height / img.height;
}
//scale the context
ctx.scale(s, s);
cts.drawImage(…);
UPDATE
It is even shorter this way (no ratios, no if):
var s = Math.max(canvas.width/img.width, canvas.height/img.height);
to fit the image use Math.min.

blurred text when a canvas is placed on top of another canvas

I want to display the mouse's x position on canvas as mouse moves. Can someone please tell why the text is so big and blurry and also is there any way to achieve the transparency between these two canvases
<body style="margin: 0; padding: 0; height: 100%; width: 100%; overflow: hidden;">
<canvas id="myCanvas" style="display: block; height: 100%; width: 100%;">
Your browser does not support the HTML5 canvas tag.</canvas> <canvas id="temp">
Your browser does not support the HTML5 canvas tag.</canvas>
<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var hgap = 0;
var vgap = 0;
var rows, cols;
var annotation_x = 1;
var row = 0; var col = 0;
//ctx.font = "14px Arial";
var t = document.getElementById("temp");
tctx = t.getContext("2d");
// tctx.lineWidth = 10;
tctx.lineJoin = 'round';
tctx.lineCap = 'round';
tctx.strokStyle = 'red';
var mouse = { x: 0, y: 0 };
c.addEventListener('mousemove', function (evt) {
// tctx.clearRect(0, 0, c.width, c.height);
ctx.clearRect(0, 0, c.width, c.height);
mouse.x = evt.pageX;
mouse.y = evt.pageY;
ctx.fillText(mouse.x, 10, 10);
}, false);
</script>
</body>
The problem isn't due to having two canvas.
The problem is that you scale your canvas using CSS, but you don't modify its number of pixels (height and width attributes). Then, the result is blurry.
If you don't scale it with CSS, the result is fine: Demo
Alternatively, you can try using image-rendering CSS property (e.g. crisp-edges, demo)
You can also modify height and width attributes when the browser is resized (resize event), and redraw the canvas.
<canvas id="myCanvas" style="display: block; height: 100%; width: 100%;">
^ You shouldn't scale a canvas element with CSS unless you want it's contents to be interpolated. Consider a 300x125px image, which you've scaled to the width and height of the browser window - the image will become blurry.
If you wish to have a full-screen canvas you need to scale it with JS:
var c = document.getElementById("myCanvas");
c.width = window.innerWidth;
c.height = window.innerHeight;
..or with HTML:
<canvas width="1920" height="1080"></canvas>

Bad quality for 100% both width and height of canvas

I have done a very tiny example with canvas, it's available on JsFiddle:
http://jsfiddle.net/yPtr5/
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
html, body {
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
}
#myCanvas {
width: 100%;
height: 100%;
display: block;
}
</style>
</head>
<body>
<canvas id="myCanvas">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script>
var canvas = document.getElementById( "myCanvas" );
var context = canvas.getContext( "2d" );
context.id = "myContext";
context.beginPath();
context.arc( 95, 50, 40, 0, 2 * Math.PI );
context.stroke();
setTimeout( function() {
var rectWidth = 150;
var rectHeight = 75;
context.fillStyle = "blue";
context.fillRect( rectWidth / -2, rectHeight / -2, rectWidth, rectHeight );
}, 2000 );
</script>
</body>
</html>
As you are able to see, the rendering result has a very low quality:
So, I'm wondering, how can I draw various figures using Canvas in a good quality, I don't want to draw in small size, I want to draw in 100% size of page.
So, maybe I didn't define some anti aliasing filter or something else?
Thanks!
Problem
In most general cases we should avoid using CSS to set the canvas size.
The default size of canvas is 300 x 150 pixels (bitmap). If you set the size using CSS we'll just end up scaling those 300 x 150 pixels meaning the browser will start interpolating and smoothing the image, which is why you end up with a blurry result.
Solution
Remove these from the CSS-rule:
#myCanvas {
/*width: 100%;
height: 100%;*/
display: block;
}
and set the size in JavaScript like this:
var canvas = document.getElementById( "myCanvas" );
canvas.width = window.innerWidth; // equals window dimension
canvas.height = window.innerHeight;
You can of course set any other size you need (in pixels). You probably want to define position (i.e. fixed or absolute) for the canvas' CSS as well if your goal is full window size.
Hope this helps.
The height and width need to be set on the height and width attributes of the canvas tag and not in CSS. Any CSS sizing of the canvas element merely stretches the canvas and does not size it properly.
<canvas id="canvas" width="500px" height="500px">
Have a look at this project that I posted on my site: Creating an HTML5 Paint App
It includes a functionto resize the canvas when the browser window size changes (which you would have to modify):
this.onScreenSizeChanged = function (forceResize) {
if (forceResize || (this.canvas.width != window.innerWidth /*||
this.canvas.height != window.innerHeight*/)) {
var image = this.context.getImageData(0, 0,
this.canvas.width, this.canvas.height);
this.canvas.width = (window.innerWidth);
this.canvas.height = (window.innerHeight);
this.context.putImageData(image, 0, 0);
}
}
this.onScreenSizeChanged(true);
In my case, it was a problem with the screen pixel ratio.
To solve it, I created a canvas with a higher pixel ratio as follows:
function createHiPPICanvas(w, h) {
let ratio = window.devicePixelRatio;
let cv = document.createElement("canvas");
cv.width = w * ratio;
cv.height = h * ratio;
cv.style.width = w + "px";
cv.style.height = h + "px";
cv.getContext("2d").scale(ratio, ratio);
return cv;
}
Then I also increased accordingly the pixel ratio of the images used inside of the canvas.

How to calculate shape height and width including its border width in canvas?

I am working on a project using HTML5 and javascript.I have a canvas on which document will be loaded.
canvas = document.getElementById('pdf');
ctx = canvas.getContext('2d');
In above canvas, document will be loaded.
I have to draw different shapes on it as an individual canvas at runtime.So that on drawing i have to create a new canvas for each and every Shape (required).
MouseDown
function mouse_Pressed(e) {
getMouse(e);//getting current X and Y position
x1=mx; y1=my;
var cords=getMousePos(canvas,e);
annCanvas=document.createElement('canvas'); //Creating
annCanvasContext=annCanvas.getContext('2d');
isDraw=true;isDrawAnn=true;
}
MouseMove
function mouse_Dragged(e)
{
if(isDraw)
{
getMouse(e);
x2=mx; y2=my;
calculatePoints(x1,y1,x2,y2);
var width=endX-startX;
var height=endY-startY;
annCanvas.style.position = "absolute";
annCanvas.width=4; //Width of square
annCanvas.style.left=""+startX+"px";
annCanvas.style.top=""+startY+"px";
annCanvas.height=height;
annCanvas.style.zIndex="100000";
document.getElementById("canvas").appendChild(annCanvas);
annCanvasContext.fillStyle='rgb(255,255,0)';
annCanvasContext.lineWidth=borderWidth;
annCanvasContext.strokeRect(0,0,width,height);
annCanvasContext.stroke();
}
}
MouseReleased
function mouse_Released(e)
{
isDrag = false;
isDraw=false;
isDrawAnn=false;
}
Main problem is that if i am drawing rectangle with border width 50 then its Canvas-outside part is going to cut because of less area of canvas(i.e. rect shape). So i want to calculate canvas height, width with its borderWidth.
This should take into account the border width as well as width etc.
function init() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var s = size(canvas);
alert(s[0]);
}
function size(el) {
var clientHeight = (el.offsetHeight > el.clientHeight) ? el.offsetHeight : el.clientHeight;
var clientWidth = (el.offsetWidth > el.clientWidth) ? el.offsetWidth : el.clientWidth;
return [clientWidth, clientHeight];
};
HTML:
<body onload="init();">
<canvas id="canvas" width="200" height="300" style="width: 500px; height: 400px; border: 10px solid brown;"></canvas>
</body>

Categories

Resources