I need a function for my simple canvas in javascript:
The function determines where the mouse pointer is on the canvas and outputs the coordinates into two variables, pointerX, and pointerY.
The function constantly updates so the variables are always accurate.
Thank you for your time, and if you have any questions for details unmentioned, please reply below and I will respond. Thanks!
Take a look at MouseEvent
and here you go:
var canvas = document.querySelector("canvas");
var h1 = document.querySelector("h1");
canvas.addEventListener("mousemove", function(e){
var x = e.pageX - canvas.offsetLeft;
var y = e.pageY - canvas.offsetTop;
h1.innerText = `x:${x},y:${y}`
})
canvas{
border:solid;
}
<canvas width="100" height="100"></canvas>
<h1></h1>
Related
I've been playing around with the HTML5 canvas lately and one of the things I've wanted to do is create a simple page with a canvas that'll draw a circle wherever you click. I have some code that looks like it should work, and I've been attempting to debug with some console output, but I've been unable to see any errors at the moment.
I'm using Codepen though, so I'm unsure how fully featured that console is, and I unfortunately can't use the dev console on my laptop at the moment (locked down school Chromebook).
Could someone take a look? I'll put the code in here and drop a link to the pen as well. Thanks!
HTML:
<canvas id="canvas" onclick="drawCircle(event)"></canvas>
CSS:
canvas {
position: relative;
background: #f1c40f;
width: 100%;
height: 100%;
}
JS:
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
function drawCircle(e) {
var pos = getCursorPosition(c, e);
var clickX = pos.x;
var clickY = pos.y;
ctx.fillStyle = "#2980b9";
ctx.beginPath();
ctx.arc(clickX, clickY, 10, 0, 2 * Math.PI);
ctx.fill();
console.log(clickX, clickY);
console.log("drawcircle");
}
function getCursorPosition(canvas, e) {
// Gets click position
rect = canvas.getBoundingClientRect();
console.log('getcursorpos');
return {
x: e.clientX - rect.left,
y: e.clientY - rect.top
};
}
Codepen link: https://codepen.io/wolverine1621/pen/gWvjgx
Any help is appreciated. It's probably something pretty simple but this is really my first time working with canvas, so any input is helpful!
Thanks!
The issue is occurring because, you set the canvas's width and height using css.
You should rather set it using javascript, like so ...
c.width = window.innerWidth;
c.height = window.innerHeight;
and to make the canvas flexible, so that it maintains it's size, use ...
window.onresize = function() {
c.width = window.innerWidth;
c.height = window.innerHeight;
}
Here is the working codepen
A couple of things:
1) you are not setting a width and height for your canvas, so there is going to be distortion and the x/y values are going to be weird. Solution: set the width and height of the canvas to the window height and width
2) Your method for determining clickX and clickY is overly complicated. Solution: use event.clientX and event.clientY
After getting your context, set the width and height:
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
Note: I would also encourage you to remove the margin on the body in CSS
body { margin: 0 }
Now you can get rid of getCursorPosition (because it is giving you wrong values)
var clickX = e.clientX
var clickY = e.clientY
So I hit a snag while building an HTML5 canvas UI element. I want to make the circle in this toggle switch drag to the X-coordinate that the user drags it to (there's ultimately a lot more that this thing is going to have but I want to do it a step at a time!). I can output the x coordinates so I know that's working but for some reason I cannot get it to work in my animation loop to change the variable primX. Here's my code:
HTML:
<canvas id="toggle1" class="toggle" onmousemove="getCoords(event)"></canvas>
<p id="test"></p>
The CSS is irrelevant, as long as you set any width to .toggle or #toggle1
JavaScript:
var canvas=document.getElementById("toggle1");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height=cw/3;
var PI=Math.PI;
var PI2=(PI * 2);
var cx=ch/2;
var cy=ch/2;
var backStyle="#FFFFFF"
var globalID;
var lw=ctx.lineWidth=8;
var radius=ch/2-lw/2;
var half=cw/2;
var currX;
var globalID;
var mouseIsDown=false;
function getCoords(event) {
var currX = event.clientX;
document.getElementById("test").innerHTML = currX;
}
function backGround(){
if (primX > half){
Style="#00FF00";
} else {
Style="#FF0000";
};
ctx.fillStyle=backStyle;
ctx.strokeStyle=Style;
ctx.beginPath();
ctx.arc(cx+lw/2,cy,radius,(0.5 * PI),(1.5 * PI));
ctx.lineTo((cw-(ch/2)),0+lw/2);
ctx.arc((cw-(ch/2+lw/2)),cy,radius,(1.5 * PI),(.5 * PI));
ctx.lineTo(cx,ch-lw/2);
ctx.fill();
ctx.stroke();
};
function mainCir() {
if (primX > half){
Style="#00FF00";
on=true;
} else {
Style="#FF0000";
on=false;
};
ctx.beginPath();
ctx.arc(primX,cy,radius,0,PI2);
ctx.fillStyle=Style;
ctx.fill();
}
primX = cx;
function draw(){
backGround();
mainCir();
}
draw();
function animate() {
primX=currX;
globalID=requestAnimationFrame(animate);
draw();
}
$("#toggle1").mousedown(function() {
mouseIsDown=true;
});
$(document).mouseup(function() {
if(mouseIsDown){
animate();
mouseIsDown=false;
}
});
I've tried a ton of different things but nothing work. If I put a simple animation in the animate() function then that seems to work when the mouse is clicked and held on the element, such as primX++;
But I have no idea how to "animate" the circle to where it goes to the X coordinate that the user drags it to. I've tried a couple of different things and rearranged stuff but it just ends up either disabling animations completely or, as you can see by THIS FIDDLE the circle just disappears.
If anyone knows how to fix this issue, I'd be grateful. Thank you!
It was a little thing. In the function that get the coordinates:
function getCoords(event) {
var currX = event.clientX;
document.getElementById("test").innerHTML = currX;
}
you are declaring the currX variable. But it was alredy declared, so what you are doing is to create a new one whose scope get lost in the moment the function finish.
You want this:
function getCoords(event) {
currX = event.clientX;
document.getElementById("test").innerHTML = currX;
}
Hope it helps!
UPDATE:
There are two more details that maybe are useful for you:
First: you are getting the coordinates in the application's client area, not in the canvas. So maybe you want to add the canvas' left offset.
Second: canvas.width is the logical canvas width, different from the element.width CSS attribute. So most sure you want to make a units conversion.
Altogether:
function getCoords(event) {
currX = event.clientX - $(event.target).offset().left ;
currX = currX * (canvas.width / $(canvas).width());
if (currX < radius) currX = radius;
if (currX > canvas.width - radius) currX = canvas.width - radius;
document.getElementById("test").innerHTML = currX;
}
Here you can read more about getting mouse coordinates and here about the dimensions of a canvas.
Is it possible to create HTML5 canvas dynamically with the mouse?
For example: I want to use my mouse to draw HTML5 canvas then load content into the different canvas.
3 hour I search over the internet for a demo and I found nothing about that possibility.
You can create a canvas on the mouse location
http://jsfiddle.net/v4nm487b/
document.onmousedown=mouseDown;
document.onmouseup=mouseUp;
var x1,y1;
function mouseDown(e){
x1=e.clientX;
y1=e.clientY;
}
function mouseUp(e){
var can = document.createElement("CANVAS");
can.style.position = "absolute";
can.style.left = x1+"px";
can.style.top = y1+"px";
can.width=Math.abs(x1-e.clientX);
can.height=Math.abs(y1-e.clientY);
can.style.border="1px solid black"
document.body.appendChild(can);
}
But what do you mean with load the content?
edit: dynamic content
You can give the canvas an id and use that to draw on it
In this exemple the created canvases have the id canN (can0,can1,canN)
If we presse 0 on the numpad (keycode 48), I fill canvas can(48-48)= can0
This ofcourse only work up to 9 but it does prove it can(vas) be done
http://jsfiddle.net/v4nm487b/6/
I can't say this for certain, as I've never tried it, but you might look into the mousedown and mouseup events. You could create an element that the user can drag in and listen for those events on it like this:
var startX, startY, endX, endY;
$('#drag')
.mousedown(function(e) {
startX = e.pageX;
startY = e.pageY;
$('#start').text(startX + ", " + startY);
})
.mouseup(function(e) {
endX = e.pageX;
endY = e.pageY;
$('#end').text(endX + ", " + endY);
});
#drag {
width: 100%;
height: 500px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="start"></div>
<div id="end"></div>
<div id="drag"></div>
That gives you the start and end positions of the drag, you can then append a canvas element with some absolute positioning based on those coordinates. Hope this helps!
I have a a canvas inside another canvas.
<canvas id ='canvas2' height="718" width="1316"></canvas>
its css is something
#canvas2{
position:absolute;
width :95%;
height:90%;
top:5%;
left:2.5%;
background: #ffff56;
cursor:pointer;
}
next I have drawn some rectangles on it. I need to colour those with mouse click. I used an action listener.
var canvas = document.getElementById("canvas2");
var ctx = canvas.getContext("2d");
canvas.addEventListener("mousedown", doMouseDown, false);
var $canvas = $("#canvas2");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
function doMouseDown(event){
event.preventDefault();
event.stopPropagation();
var x= parseInt(event.clientX - offsetX);
var y = parseInt(event.clientY - offsetY);
}
But this is not the right way I know as I am getting all the wrong canvas co-ordinates on x and y.
Can someone show the right way?
Has your canvas been scrolled?
If yes, then you also need to account for the distance the canvas has been scrolled in the browser.
You might check out canvas.getBoundingClientRect() as a way to get the canvas position with the scrolling accounted for:
function handleMousemove(e){
e.preventDefault();
e.stopPropagation();
// if the canvas is stationary (not scrolling) then you can do
// .getBoundingClientRect once at the start of the app
var BB=canvas.getBoundingClientRect();
// calc mouse position based on the bounding box
var mouseX=parseInt(e.clientX-BB.left);
var mouseY=parseInt(e.clientY-BB.top);
console.log(mouseX+"/"+mouseY);
}
I want to be able to orient something toward the mouse on an HTML5 canvas. But when I use Math.atan2 and the other trig functions, the directions get messed up. It rotates in the opposite direction that it should and it's usually off by 90 degrees.
It will probably be easier if you see it for yourself. Here's the javascript:
var mouseX=0;
var mouseY=0;
var canvas = document.getElementById("world");
var context = canvas.getContext("2d");
function mouseMoveHandler(event) {
mouseX = event.clientX;
mouseY = event.clientY;
}
function windowResizeHandler() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
function loop() {
// Clear Screen
context.clearRect(0,0,canvas.width,canvas.height);
// Calculate the angle to the mouse
a = Math.atan2(mouseX-canvas.width/2,mouseY-canvas.height/2);
// Draw a line in the direction of the mouse
context.beginPath();
context.fillStyle = "#000000";
context.moveTo(canvas.width/2+10, canvas.height/2);
context.lineTo(canvas.width/2-10, canvas.height/2);
context.lineTo(canvas.width/2+Math.cos(a)*100, canvas.height/2+Math.sin(a)*100);
context.fill();
}
document.addEventListener('mousemove', mouseMoveHandler, false);
window.addEventListener('resize', windowResizeHandler, false);
windowResizeHandler();
setInterval(this.loop, 1000 / 30 );
And here's the HTML:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<canvas id='world'></canvas>
<script type="text/javascript" src="test.js"></script>
</body>
</html>
You can see it in action here: http://sidefofx.com/projects/stackOverflowQuestion/
How can I make the line point in the direction of the mouse?
I rechecked and what you're doing wrong (and I've done this error a few times myself) is that atan2 accepts first the y coordinate, then the x coordinate.
MDC says:
Note that the arguments to this function pass the y-coordinate first and the x-coordinate second.
So
a = Math.atan2(mouseX-canvas.width/2,mouseY-canvas.height/2);
should be
a = Math.atan2(mouseY-canvas.height/2, mouseX-canvas.width/2);
Test updated: http://jsfiddle.net/79FaY/1/