Why the coordinates of mouse in canvas are wrong? - javascript

I intend to draw free with the mouse cursor in canvas. My code seems to do the part with color but it doesn't take the exact coordinates of my current mouse position in canvas when i draw.
<body>
<canvas id="canvas" style=" width: 400; height: 400px; background-color:yellow; position: absolute; margin-left:100px; margin-top:30px"></canvas>
<script>
var Color = 'blue';
var Canvas = document.getElementById('canvas');
var Context = Canvas.getContext('2d');
$("canvas").on("mousemove",function(e){
X = e.clientX - canvas.offsetLeft;
Y = e.clientY - canvas.offsetTop;
Context.strokeStyle = Color;
Context.lineWidth = 3;
Context.lineCap = 'round';
Context.beginPath();
Context.moveTo(X,Y);
Context.lineTo(X,Y);
Context.fillRect(X,Y, 3,3)
Context.stroke();
Context.closePath();
});
</script>
</body>
https://jsfiddle.net/93L8mLnf/
I tested in console.log the coordinates and they are corect. I'm confused..

You need to synchronize the dimension of the canvas with the DOM element.
Add this:
Canvas.width = Canvas.clientWidth;
Canvas.height = Canvas.clientHeight;
Demonstration
You'll also notice the canvas isn't blurred anymore.
Note that this must be done every time the canvas DOM element changes size (usually because the window is resized) so when your element isn't of fixed size you should bind an event handler on the window resize event to do that synchronization again (and usually to redraw the content).

You have to add width and height by canvas attributes
see in fiddle
<canvas id="canvas" style="background-color:yellow;" width="250" height="250"></canvas>

Related

Canvas Element - Rotation

I've multiple canvas elements, each one work on his own. I would like to use these to create a multiplayer. It works perfectly, but now I would like to rotate single canvas elements (180 degree). I tried the getContext('2d') method but it only helps me for a single obeject on the canvas. But what I would like to do is to rotate the WHOLE canvas.
Does someone know how I can do this?
Feilx
You could utilize CanvasRenderingContext2D.rotate() and CanvasRenderingContext2D.translate methods for that purpose, the following example illustrates it:
var canvas = document.getElementById("canvas");
var angleInput = document.getElementById("angleInput");
canvas.width = 800;
canvas.height = 600;
var ctx = canvas.getContext("2d");
var angleInDegrees=0;
drawRotated(ctx,angleInDegrees);
document.getElementById("clockwiseButton").addEventListener('click',function(){
angleInDegrees+=parseInt(angleInput.value);
drawRotated(ctx,angleInDegrees);
});
document.getElementById("counterclockwiseButton").addEventListener('click',function(){
angleInDegrees-=parseInt(angleInput.value);
drawRotated(ctx,angleInDegrees);
});
function drawRotated(ctx,degrees){
var canvasWidth = ctx.canvas.width;
var canvasHeight = ctx.canvas.height;
ctx.clearRect(0,0,canvasWidth,canvasHeight); // Clear the canvas
ctx.save();
ctx.translate(canvasWidth/2,canvasHeight/2); // Move registration point to the center of the canvas
ctx.rotate(degrees*Math.PI/180); // Rotate
drawObjects(ctx);
ctx.restore();
}
function drawObjects(ctx)
{
//draw triangle
ctx.beginPath();
ctx.moveTo(200,150);
ctx.lineTo(150,200);
ctx.lineTo(250,200);
ctx.fill();
//draw circle
ctx.beginPath();
ctx.arc(350,75,50,0,Math.PI*2,false);
ctx.fill();
ctx.stroke();
//draw rectangle
ctx.fillRect(50,50,150,50);
}
<div>
<button id="clockwiseButton">Rotate right</button>
<button id="counterclockwiseButton">Rotate left</button>
<input id="angleInput" value="45"></input>
</div>
<canvas id="canvas"></canvas>
JSFiddle

image resize and then rotate in canvas - javascript

I am using an image with size 1024 x 768 and I have a canvas size 300 x 300 so I want to resize my image first to 300 x 300 and then rotate it within the canvas proportionally.
I am using following code but it is resizing the image but rotating some elements outside the canvas. So if you click right then you dont see anything and then hit right again then you will the image with down rotated.
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var degrees=0;
var image=document.createElement("img");
image.onload=function(){
ctx.drawImage(image,0,0,300,300);
}
image.src="http://media1.santabanta.com/full1/Outdoors/Landscapes/landscapes-275a.jpg";
image.width = 300;
image.height = 300;
$("#clockwise").click(function(){
degrees+=90
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();
ctx.translate(300,300);
ctx.rotate(degrees*Math.PI/180);
ctx.drawImage(image,0,0,300,300);
ctx.restore();
});
Please check my code in JSFiddle as well
http://jsfiddle.net/6ZsCz/914/
Try this variation.
Translate to the center of the canvas.
DrawImage with an [x,y] offset of image.width/2 & image.height/2. This offset is required because translate effectively makes the canvas centerpoint[150,150] to be the new canvas origin[0,0]. You need the negative offset to pull the drawing leftward and upward to compensate for the new origin.
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var degrees=0;
var image=document.createElement("img");
image.onload=function(){
ctx.drawImage(image,0,0,300,300);
}
image.src="http://media1.santabanta.com/full1/Outdoors/Landscapes/landscapes-275a.jpg";
$("#clockwise").click(function(){
degrees+=90
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();
ctx.translate(150,150);
ctx.rotate(degrees*Math.PI/180);
ctx.drawImage(image,0,0,image.width,image.height,-150,-150,300,300);
ctx.restore();
});
body{ background-color: ivory; }
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<canvas id="canvas" width=300 height=300></canvas><br>
<button id="clockwise">Rotate right</button>

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>

How to draw canvas elements in the right positions?

I am using javascript to draw a rectangle around DOM elements in a website.
The problem is that the rectangles are drawn in the wrong positions.
I know that canvas, work like a real canvas so you have to "predraw" everything before filling the canvas, otherwise the elements will be on top of each other, in the orders you drew them.
That's why I'm defining canvas, and context outside of the loop.
This is my code:
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
context.globalAlpha = 0.5;
//Set canvas width/height
canvas.style.width='100%';
canvas.style.height='100%';
//Set canvas drawing area width/height
canvas.width = document.width;
canvas.height = document.height;
//Position canvas
canvas.style.position='absolute';
canvas.style.left=0;
canvas.style.top=0;
canvas.style.zIndex=100000;
canvas.style.pointerEvents='none'; //Make sure you can click 'through' the canvas
document.body.appendChild(canvas); //Append canvas to body element
var listingsRect = Array.prototype.map.call(document.querySelectorAll('.rc'), function(e) {
return e.getBoundingClientRect();
});
listingsRect.forEach(function(listingRect) {
var x = listingRect.left;
var y = listingRect.top;
var width = listingRect.width;
var height = listingRect.height;
//Draw rectangle
context.rect(x, y, width, height);
context.fillStyle = 'yellow';
context.fill();
});
However, when I change
canvas.width and canvas.height to window.innerWidth and window.innerHeight respectively, then canvas draws the rectangles in the right positions, however it only draws them in the visible area of the website (obviously).
Can somebody tell me what's wrong with my code?
Here's a JS bin:
http://jsbin.com/elUToGO/1
The x,y in context.rect(x,y,width,height) are relative to the canvas element not to the browser window.
So if your canvas element is absolutely positioned at 50,75 and you want a rect at window position 110,125 you would draw your rect like this:
context.rect( 110-50, 125-75, width, height );
A few other things:
If you set the canvas element width/height and then position absolutely, you don't need canvas.style.width/height.
document.width/height are deprecated (& not supported in IE) . Use this instead:
//Set canvas drawing area width/height
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
When setting style.left/top, you might want to pass a string with "px" in case you later set >0.
canvas.style.left="0px";
canvas.style.top="0px";
.pointerEvents='none' is supported in most browsers (but not in IE<11)

width specify in px or not changes canvas behaviour

I'm trying to draw a rectangle by dragging mouse, basically follow this tutorial.
However, I found that if I specify the canvas dimension in px, it will not work. In contrast, if I use this html, this works fine:
<!DOCTYPE html>
<html>
<head>
<title>drag a rectangle</title>
<style>
#cvs {
width: 500;
height: 500;
border: 1px solid #666;
}
</style>
<script src="jquery-1.9.0.js"></script>
</head>
<body>
<canvas id="cvs"></canvas>
<script src="main.js"></script>
</body>
</html>
And this js:
$(document).ready(function() {
var canvas = document.getElementById('cvs');
var ctx = canvas.getContext('2d');
var rect = {};
var drag = false;
var mouseDown = function(e) {
rect.startX = e.pageX - this.offsetLeft;
rect.startY = e.pageY - this.offsetTop;
console.log(rect.startX + ' ' + rect.startY);
drag = true;
};
var mouseUp = function(e) {
drag = false;
};
var draw = function() {
ctx.fillRect(rect.startX, rect.startY, rect.w, rect.h);
};
var mouseMove = function(e) {
if (drag) {
rect.w = (e.pageX - this.offsetLeft) - rect.startX;
rect.h = (e.pageY - this.offsetTop) - rect.startY;
console.log(rect.w + ' ' + rect.h);
ctx.clearRect(0, 0, canvas.width, canvas.height);
draw();
}
};
function init() {
canvas.addEventListener('mousedown', mouseDown, false);
canvas.addEventListener('mouseup', mouseUp, false);
canvas.addEventListener('mousemove', mouseMove, false);
}
init();
});
It works fine. However, if I specify the dimension in px, i.e.,
#cvs {
width: 500px;
height: 500px;
border: 1px solid #666;
}
The mouse location and the rectangle no longer align. Also, the dimension in the viewport is also different. I suppose it's a fundamental question, but what is the difference between specify the px or not? And how does that influence my drag rectangle behavior?
Tested locally on the latest Chrome.
To set the size of your canvas, use the canvas element attributes width and height.
<canvas width="400" height="300">Not supported</canvas>
When the page loads the canvas size is set to it's width and height. If style.width and/or style.height are set, the canvas will scale to fit the dimensions specified in these styles.
Here is an example.
So now about your question. As I wrote above when you set style.width and style.height as:
#cvs {
width: 500px;
height: 500px;
border: 1px solid #666;
}
The width and height will apply and the canvas will scale it's size, so the point with coordinates (x, y) won't appear where you expect. For example, if you try to draw a point with coordinates (500, 500) you probably won't see it at all, because simply your canvas coordinate system's dimensions are less than that. When you don't specify px you simply don't provide valid width and height and your style does not apply correctly so your canvas is not scaled and everything works as you expect.

Categories

Resources