Why this holding event mouse doesn't for a canvas painting? - javascript

Can somebody give me some help?, I don't understand why it doesn't work, I tried everything but I just don't understand it, I'm beginner.
I'm trying to make a holding mouse event for a canvas painting, I tried making a while loop you hold it and it will paint in the canvas but it doesn't work so I tried making the loop say "Hello" in console... but it doesn't work.
document.addEventListener("mousedown", holding)
document.addEventListener("mouseup", noHolding)
var hold;
function holding(){
hold = true;
console.log("hold: " + hold)
}
function noHolding(){
hold = false;
console.log("hold: " + hold)
}
while(hold == true){
console.log("Holding")
}

You have to think about the order of execution.
Your code gets executed line by line (more or less). So in your example these are the steps:
declare function holding
declare function noHolding
declare variable hold
bind holding to the mousedown event
bind noHolding to the moueup event
define function holding
define function noHolding
loop while hold == true
the value of hold, at this point in time is undefined, so the loop does not run
finish execution
function and var declarations are moved (hoisted) to the top of their function, or global if not in a function, scope.
Later when you press down your mouse button hold will be set to true but the while(hold==true) statement has already been executed and will not run again.
You should avoid loops in javascript that will run for more than a few milliseconds because it they will stop any other code from running (generally).
You can instead use the mousemove event. (example included)
Example from MDN:
// When true, moving the mouse draws on the canvas
let isDrawing = false;
let x = 0;
let y = 0;
const myPics = document.getElementById('myPics');
const context = myPics.getContext('2d');
// The x and y offset of the canvas from the edge of the page
const rect = myPics.getBoundingClientRect();
// Add the event listeners for mousedown, mousemove, and mouseup
myPics.addEventListener('mousedown', e => {
x = e.clientX - rect.left;
y = e.clientY - rect.top;
isDrawing = true;
});
myPics.addEventListener('mousemove', e => {
if (isDrawing === true) {
drawLine(context, x, y, e.clientX - rect.left, e.clientY - rect.top);
x = e.clientX - rect.left;
y = e.clientY - rect.top;
}
});
window.addEventListener('mouseup', e => {
if (isDrawing === true) {
drawLine(context, x, y, e.clientX - rect.left, e.clientY - rect.top);
x = 0;
y = 0;
isDrawing = false;
}
});
function drawLine(context, x1, y1, x2, y2) {
context.beginPath();
context.strokeStyle = 'black';
context.lineWidth = 1;
context.moveTo(x1, y1);
context.lineTo(x2, y2);
context.stroke();
context.closePath();
}
canvas {
border: 1px solid black;
width: 560px;
height: 360px;
}
<h1>Drawing with mouse events</h1>
<canvas id="myPics" width="560" height="360"></canvas>

Related

Html5 Canvas - dynamic table pushed canvas down and now the draw/image is not showing

I am using HTML5 Canvas with JavaScript. In the HTML layout, the canvas has a dynamic table above it. The table size is not static and changes at run-time depending on the parameter given. The problem I have is that when the table becomes long, it pushes the canvas down and the drawn image no longer shows. I know the drawn image is there because when I apply the following style code:
canvas {
position: absolute;
top: 0px;
left: 0px
}
the canvas moves to the top and the drawn image appears. Also, when the table is short, the canvas works fine.
I have tried using absolute and relative positioning on the table and canvas elements but that is not helping. I have tried getting the height of the table and applying a margin top to the canvas at run time but that didn't work. I have tried offsets, but they are not working either. I don't know what to do in order to keep the drawn image with the canvas element.
//declare variables
var canvas, context, flag = false;
var offsetX, offsetY;
var prevX; //initial position of mouse along x-axis
var currX; //new position of mouse along x-axis, initially set to 0
var prevY; //initial position of mouse along y axis
var currY; //new position of mouse along y axis, initially set to 0
var dot_draw = false;
var font_color = "black";
function startSignaturePad() {
canvas = document.getElementById('signaturepad'); //get the canvas element
if (canvas) {
context = canvas.getContext("2d"); //get the 2d drawing context
canvas.width = 400;
canvas.height = 150;
width = canvas.width;
height = canvas.height;
}
function reOffset() {
var BB = canvas.getBoundingClientRect();
offsetX = BB.left;
offsetY = BB.top;
}
reOffset();
window.onscroll = function(e) {
reOffset();
}
window.onresize = function(e) {
reOffset();
}
//bind the event listeners to the canvas
canvas.addEventListener("mousemove", function onMouseMove(e) {
getPositionXY('move', e)
}, false);
canvas.addEventListener("mousedown", function onMouseDown(e) {
getPositionXY('down', e)
}, false);
canvas.addEventListener("mouseup", function onMouseUp(e) {
getPositionXY('up', e)
}, false);
canvas.addEventListener("mouseout", function onMouseOut(e) {
getPositionXY('out', e)
}, false);
}
function draw() { //function to draw a dot at a specific position - grabs and then draws the position of x and y
context.beginPath();
context.moveTo(prevX, prevY);
context.lineTo(currX, currY);
context.strokeStyle = font_color;
context.lineWidth = font_size;
context.stroke();
context.closePath();
}
function erase() { //erase what is on the canvas
var erase = confirm("Are you sure you want to erase?");
if (erase) {
context.clearRect(0, 0, width, height);
}
}
function getPositionXY(mouse, e) {
if (mouse == 'down') {
prevX = currX; //reset previous position of x and y
prevY = currY;
currX = (e.clientX - canvas.offsetLeft) < (e.clientX - canvas.offsetX) ? e.clientX - canvas.offsetX : e.clientX - canvas.offsetLeft; //set new position of x and y
currY = (e.clientY - canvas.offsetTop) < (e.clientY - canvas.offsetY) ? e.clientY - canvas.offsetY : e.clientY - canvas.offsetTop;
flag = true;
dot_draw = true;
if (dot_draw) { //draw path while mouse is pressed down
context.textBaseline = "hanging";
context.beginPath();
context.fillStyle = font_color;
context.arc(currX, currY, 2, 0, 2 * Math.PI);
context.closePath();
dot_draw = false;
}
}
if (mouse == 'up' || mouse == "out") {
flag = false; //when mouse is released do nothing
}
if (mouse == 'move') {
if (flag) {
prevX = currX;
prevY = currY;
currX = (e.clientX - canvas.offsetLeft) < (e.clientX - canvas.offsetX) ? e.clientX - canvas.offsetX : e.clientX - canvas.offsetLeft;
currY = (e.clientY - canvas.offsetTop) < (e.clientY - canvas.offsetY) ? e.clientY - canvas.offsetY : e.clientY - canvas.offsetTop;
draw();
}
}
}
canvas {
position: absolute;
top: 0px;
left: 0px
}
<div>
<table>
<!-- some code -->
</table>
</div>
<div id="sigCanvas">
<canvas id="signaturepad" style="border:1px solid;"></canvas>
</div>
Since your canvas can move around, you want the latest position, so get it at the last possible instant.
Since your code works when the canvas is at (0,0), just adding
a call to reOffset() and the very beginning of getPositionXY() might do the trick.
If not, here is how I locate a mouse click relative to the canvas:
function locateMouse(evnt)
{
var x = evnt.pageX;
var y = evnt.pageY;
var c = canvas.getBoundingClientRect();
x = Math.floor(x) - c.left;
y = Math.floor(y) - c.top;
/// then use x and y however you want
}

Detect if Mouse is over an object inside canvas

I have created a line inside a canvas element. I am looking for the easiest way to detect if the position of the mouse is inside the line, which is inside the canvas.
I have used this function to see the position of the mouse inside the canvas, but I am very confused on how I should proceed.
function getMousePos(c, evt) {
var rect = c.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
I have also looked at this topic Fabricjs detect mouse over object path , but it detects if the mouse is inside the canvas, not inside the object.
The line that I create is a part of smaller lines, connected to each other.
for (var i = 0; i < 140 ; i++) {
ctx.beginPath();
ctx.moveTo(x[i],y[i]);
ctx.quadraticCurveTo(x[i],50,x[i+1],y[i+1]);
ctx.lineWidth = 40;
ctx.strokeStyle = 'white';
ctx.lineCap = 'round';
ctx.stroke();
}
where x[i] and y[i] are the arrays with the coordinates that I want.
I hope my question is clear, although I am not very familiar with javascript.
Thanks
Dimitra
A Demo: http://jsfiddle.net/m1erickson/Cw4ZN/
You need these concepts to check if the mouse is inside a line:
Define the starting & ending points of a line
Listen for mouse events
On mousemove, check if the mouse is within a specified distance of the line
Here's annotated example code for you to learn from.
$(function() {
// canvas related variables
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
// dom element to indicate if mouse is inside/outside line
var $hit = $("#hit");
// determine how close the mouse must be to the line
// for the mouse to be inside the line
var tolerance = 5;
// define the starting & ending points of the line
var line = {
x0: 50,
y0: 50,
x1: 100,
y1: 100
};
// set the fillstyle of the canvas
ctx.fillStyle = "red";
// draw the line for the first time
draw(line);
// function to draw the line
// and optionally draw a dot when the mouse is inside
function draw(line, mouseX, mouseY, lineX, lineY) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(line.x0, line.y0);
ctx.lineTo(line.x1, line.y1);
ctx.stroke();
if (mouseX && lineX) {
ctx.beginPath();
ctx.arc(lineX, lineY, tolerance, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
}
}
// calculate the point on the line that's
// nearest to the mouse position
function linepointNearestMouse(line, x, y) {
//
lerp = function(a, b, x) {
return (a + x * (b - a));
};
var dx = line.x1 - line.x0;
var dy = line.y1 - line.y0;
var t = ((x - line.x0) * dx + (y - line.y0) * dy) / (dx * dx + dy * dy);
var lineX = lerp(line.x0, line.x1, t);
var lineY = lerp(line.y0, line.y1, t);
return ({
x: lineX,
y: lineY
});
};
// handle mousemove events
// calculate how close the mouse is to the line
// if that distance is less than tolerance then
// display a dot on the line
function handleMousemove(e) {
e.preventDefault();
e.stopPropagation();
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
if (mouseX < line.x0 || mouseX > line.x1) {
$hit.text("Outside");
draw(line);
return;
}
var linepoint = linepointNearestMouse(line, mouseX, mouseY);
var dx = mouseX - linepoint.x;
var dy = mouseY - linepoint.y;
var distance = Math.abs(Math.sqrt(dx * dx + dy * dy));
if (distance < tolerance) {
$hit.text("Inside the line");
draw(line, mouseX, mouseY, linepoint.x, linepoint.y);
} else {
$hit.text("Outside");
draw(line);
}
}
// tell the browser to call handleMousedown
// whenever the mouse moves
$("#canvas").mousemove(function(e) {
handleMousemove(e);
});
}); // end $(function(){});
body {
background-color: ivory;
}
canvas {
border: 1px solid red;
}
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" />
<!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
</head>
<body>
<h2 id="hit">Move mouse near line</h2>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
About hit-testing Paths:
If you create Paths using path commands you can use context.isPointInPath(mouseX,mouseY) to check if the mouse is inside a path. context.isPointInPath does not work well with lines however because lines theoretically have zero width to "hit".
this.element.addEventListener("mouseenter", (event) => {});
mouse over a div
this.element.addEventListener("mouseleave", (event) => {});
mouse leaving div

How do I make this function update the current mouse position?

I'm making a drawing pad, and I want the mouse location to update in an array as the mouse is dragged. Here is my code:
function penDown (x, y) {
isPenDown = true;
localPen.x = x;
localPen.y = y;
}
var X = [],
Y = [],
i = -1;
function penMove (x, y) {
if (isPenDown) {
++i;
X[i] = localPen.x;
Y[i] = localPen.y;
console.log("i is " + i + ", x is " + X[i] + ", y is " + Y[i]);
}
};
The console log shows that i is updating continuously when you move the mouse, but the X and Y coordinates of the mouse don't change - they just stay on the initial mouse location when you first press down the mouse.
Here is how I call penDown:
function pointerDownListener (e) {
// Retrieve a reference to the Event object for this mousedown event.
var event = e || window.event;
// Determine where the user clicked the mouse.
var mouseX = event.clientX - canvas.offsetLeft;
var mouseY = event.clientY - canvas.offsetTop;
// Move the drawing pen to the position that was clicked
penDown(mouseX, mouseY);
}
function pointerMoveListener (e) {
var event = e || window.event; // IE uses window.event, not e
var mouseX = event.clientX - canvas.offsetLeft;
var mouseY = event.clientY - canvas.offsetTop;
// Draw a line if the pen is down
penMove(mouseX, mouseY);
}
It might be, because your function penDown is only called once, so the values of x and y assigned to localPen won't change.

HTML5 Canvas Mouse Listener Coordinates Undefined

I'm attempting to take in mouse coordinates from a mouse listener but they are coming in undefined. The mouse listener is being added to the Canvas and the listener is triggering the onMouseMove function, however the event being passed doesn't seem to have any defined x or y coordinates for the mouse position.
I've tried the following variables: event.pageX, event.pageY, event.clientX, event.clientY, event.x, event.y
Any ideas on what I'm doing incorrectly to cause the mouse coordinates to come in undefined? Thanks for any help!
<script>
var boxes;
var canvas;
var context;
$(document).ready(function() {
canvas = document.getElementById("requirement_tree");
context = canvas.getContext("2d");
// Add mouse listener
canvas.addEventListener("mousemove", onMouseMove, false);
});
// Get the current position of the mouse within the provided canvas
function getMousePos(event) {
var rect = canvas.getBoundingClientRect();
if (event.pageX != undefined && event.pageY != undefined) {
x = event.pageX;
y = event.pageY;
} else {
x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
console.log("X:" + x);
console.log("Y:" + y);
return {
X: x - rect.left,
Y: y - rect.top
};
}
function onMouseMove(event) {
var mousePos = getMousePos(canvas, event);
var message = 'Mouse position: ' + mousePos.X + ',' + mousePos.Y;
context.font = '10pt Arial'
context.fillStyle = 'black';
context.textAlign = 'left';
context.clearRect(0, 0, 200, 200);
context.fillText(message, 100, 100);
}
</script>
At least, error in handler for mouseMove event. Event object transmitted in second arguments of handler.
// ...
// Get the current position of the mouse within the provided canvas
function getMousePos(element, event) {
var rect = canvas.getBoundingClientRect();
// ...

three.js rotate object on mouse down and move

I'm trying to get a good mouse movement in my scene so I can rotate around the object.
I have two problems, I can figure out how to limit the movement so that it never rotates below 0 degrees on the Y axis. (I dont want to see the object from below, only above)
And the second thing I can't figure out is how to make the movement smooth. Now with what I have achieved in the jsfiddle is that the camera moves back to its starting position before starting to rotate.
My try: http://jsfiddle.net/phacer/FHD8W/4/
This is the part I dont get:
var spdy = (HEIGHT_S / 2 - mouseY) / 100;
var spdx = (WIDTH / 2 - mouseX) / 100;
root.rotation.x += -(spdy/10);
root.rotation.y += -(spdx/10);
What I want without using an extra library: http://www.mrdoob.com/projects/voxels/#A/afeYl
You can rotate you scene with this code,
To ensure to not rotate under 0, simule rotation of a vector (0,0,1) and check if y of vector is negative
var mouseDown = false,
mouseX = 0,
mouseY = 0;
function onMouseMove(evt) {
if (!mouseDown) {
return;
}
evt.preventDefault();
var deltaX = evt.clientX - mouseX,
deltaY = evt.clientY - mouseY;
mouseX = evt.clientX;
mouseY = evt.clientY;
rotateScene(deltaX, deltaY);
}
function onMouseDown(evt) {
evt.preventDefault();
mouseDown = true;
mouseX = evt.clientX;
mouseY = evt.clientY;
}
function onMouseUp(evt) {
evt.preventDefault();
mouseDown = false;
}
function addMouseHandler(canvas) {
canvas.addEventListener('mousemove', function (e) {
onMouseMove(e);
}, false);
canvas.addEventListener('mousedown', function (e) {
onMouseDown(e);
}, false);
canvas.addEventListener('mouseup', function (e) {
onMouseUp(e);
}, false);
}
function rotateScene(deltaX, deltaY) {
root.rotation.y += deltaX / 100;
root.rotation.x += deltaY / 100;
}

Categories