How do i get update to stop running when I click? - javascript

Here is a code segment where i am trying to make update stop running so that I can put a dot on the canvas. When I try to get putPoint to return clicked = true, it makes clicked equal true regardless if I click or not. I just want to return true if and only if I click.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
//canvas.width = window.innerWidth;
//canvas.height = window.innerHeight;
var radius = 2;
var dragging = false; // wether or not the mouse button is held down
ctx.lineWidth = radius * 2;
var canvasPos = getPosition(canvas);
var mouseX = 0;
var mouseY = 0;
var clicked = false;
// here is where I declare clicked = true globally
function update() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(mouseX, mouseY, radius, 0, 2 * Math.PI, true);
ctx.fill();
requestAnimationFrame(update);
}
canvas.addEventListener("mousemove", setMousePosition, false);
function setMousePosition(e) {
mouseX = e.clientX;
mouseY = e.clientY;
}
//console.log("before update " + clicked);
if (clicked != true) {
update();
//console.log("inside update " +clicked);
}
// here is the code I want to stop when I click
//console.log("after update " + clicked);
function putPoint() {
//e.clientX and e.clientY get the mouse position
ctx.beginPath();
//e.clientX and e.clientY get the mouse position
ctx.arc(mouseX - 10, mouseY - 10, radius, 0, Math.PI * 2);
//ctx.arc(e.offsetX, e.offsetY, radius, 0, Math.PI * 2);
ctx.fill();
//console.log("inside putPoint " + clicked);
}
//putPoint puts a dot on the canvas at the mouse position. But it wont fire unless
//I stop update, which tracks my dot.
//console.log("after putPoint " + clicked);
canvas.addEventListener("mousedown", putPoint);
//console.log(putPoint());
//console.log(clicked);
function getPosition(el) {
var xPosition = 0;
var yPosition = 0;
while (el) {
xPosition += (el.offsetLeft - el.scrollLeft + el.clientLeft);
yPosition += (el.offsetTop - el.scrollTop + el.clientTop);
el = el.offsetParent;
}
return {
x: xPosition,
y: yPosition
};
}
<canvas id=myCanvas>
</canvas>
below is a smaller reproduction of the problem. basically I am trying to update my variable to true when i click on the element. But when I return true or even set clicked to to true within the test function, it still reads true wether I click or not. It doesnt dynamically change. Maybe Im using the wrong event ? im not sure.
var clicked = false;
console.log(clicked);
function test () {
return true;
}
clicked = test();
console.log(clicked);
document.getElementsByTagName("h1")[0].addEventListener("mousedown", test);

I'm inferring a bit based on clues from both the used and unused (e.g. dragging variable) parts of your first snippet, but it seems to me like you are trying to draw a point that tracks with your mouse, and then once a click event has occurred you want to start drawing points dragging after the mouse until that click is released.
First, your issue with your 'clicked' tracking
I think you are misunderstanding when different statements are executed. In your second snippet all of the statements outside of the 'test' event handler function are only executed once. The 'test' function will be called with each mouse click, but simply returns true and does not change the value of 'clicked'. So, the statement:
var clicked = false;
...and the statement:
clicked = test();
...each only execute once. Here is a quick example to show you how you could track the toggling of that value. Try a simple click and also holding the click for a second before releasing to get the idea.
var clicked = false;
var clickableArea = document.getElementById("clickable");
clickableArea.addEventListener('mousedown', function() {
clicked = true;
console.log('Clicked, value of clicked var: ' + clicked);
});
clickableArea.addEventListener('mouseup', function() {
clicked = false;
console.log('Released, value of clicked var: ' + clicked);
});
<div id="clickable">Click Me</div>
What I think you are going for with your canvas rendering:
Move the mouse around and then click and drag the mouse.
var canvas, ctx;
var radius = 2;
var mouseX = 0;
var mouseY = 0;
var clicked = false;
var dragging = false;
// manages the drawing cycle
function putPoint() {
// clear the canvas if not dragging, or just before the first draw of a dragging cycle
if(!dragging) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
dragging = clicked;
// draw
var offset = dragging ? 10 : 0;
ctx.beginPath();
ctx.arc(mouseX-offset, mouseY-offset, radius, 0, 2 * Math.PI, true);
ctx.fill();
// kick off another cycle
requestAnimationFrame(putPoint);
}
// event handlers
function trackMouse(e) {
mouseX = e.clientX;
mouseY = e.clientY;
}
function startedDragging() {
clicked = true;
}
function quitDragging() {
clicked = false;
dragging = false;
}
// only runs once when called below, sets things up, starts the drawing cycle
function start() {
canvas = document.getElementById("myCanvas");
ctx = canvas.getContext("2d");
ctx.lineWidth = radius * 2;
// attach events to handlers
canvas.addEventListener("mousemove", trackMouse, false);
canvas.addEventListener("mousedown", startedDragging);
canvas.addEventListener("mouseup", quitDragging);
requestAnimationFrame(putPoint);
}
start(); // calling start to kick things off
<canvas id="myCanvas">
</canvas>

Related

Remove point on double click on canvas

I have a canvas on which user can draw point on click on any part of it. As one know we must give the user the possibility to undo an action that he as done. This is where I'am stuck, how can I program the codes to allow the user to remove the point on double click on the the point he wants to remove ?
<canvas id="canvas" width="160" height="160" style="cursor:crosshair;"></canvas>
1- Codes to draw the canvas and load an image in it
var canvasOjo1 = document.getElementById('canvas'),
context1 = canvasOjo1.getContext('2d');
ojo1();
function ojo1()
{
base_image1 = new Image();
base_image1.src = 'https://www.admedicall.com.do/admedicall_v1//assets/img/patients-pictures/620236447.jpg';
base_image1.onload = function(){
context1.drawImage(base_image1, 0, 0);
}
}
2- Codes to draw the points
$("#canvas").click(function(e){
getPosition(e);
});
var pointSize = 3;
function getPosition(event){
var rect = canvas.getBoundingClientRect();
var x = event.clientX - rect.left;
var y = event.clientY - rect.top;
drawCoordinates(x,y);
}
function drawCoordinates(x,y){
var ctx = document.getElementById("canvas").getContext("2d");
ctx.fillStyle = "#ff2626"; // Red color
ctx.beginPath();
ctx.arc(x, y, pointSize, 0, Math.PI * 2, true);
ctx.fill();
}
My fiddle :http://jsfiddle.net/xpvt214o/834918/
By hover the mouse over the image we see a cross to create the point.
How can i remove a point if i want to after create it on double click ?
Thank you in advance.
Please read first this answer how to differentiate single click event and double click event because this is a tricky thing.
For the sake of clarity I've simplified your code by removing irrelevant things.
Also please read the comments of my code.
let pointSize = 3;
var points = [];
var timeout = 300;
var clicks = 0;
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
let cw = (canvas.width = 160);
let ch = (canvas.height = 160);
function getPosition(event) {
var rect = canvas.getBoundingClientRect();
return {
x: event.clientX - rect.left,
y: event.clientY - rect.top
};
}
function drawCoordinates(point, r) {
ctx.fillStyle = "#ff2626"; // Red color
ctx.beginPath();
ctx.arc(point.x, point.y, r, 0, Math.PI * 2, true);
ctx.fill();
}
canvas.addEventListener("click", function(e) {
clicks++;
var m = getPosition(e);
// this point won't be added to the points array
// it's here only to mark the point on click since otherwise it will appear with a delay equal to the timeout
drawCoordinates(m, pointSize);
if (clicks == 1) {
setTimeout(function() {
if (clicks == 1) {
// on click add a new point to the points array
points.push(m);
} else { // on double click
// 1. check if point in path
for (let i = 0; i < points.length; i++) {
ctx.beginPath();
ctx.arc(points[i].x, points[i].y, pointSize, 0, Math.PI * 2, true);
if (ctx.isPointInPath(m.x, m.y)) {
points.splice(i, 1); // remove the point from the array
break;// if a point is found and removed, break the loop. No need to check any further.
}
}
//clear the canvas
ctx.clearRect(0, 0, cw, ch);
}
points.map(p => {
drawCoordinates(p, pointSize);
});
clicks = 0;
}, timeout);
}
});
body {
background: #20262E;
padding: 20px;
}
<canvas id="canvas" style="cursor:crosshair;border:1px solid white"></canvas>

How to delete particular circle when user creates multiple circles by dragging mouse on screen using Javascript

I created circles using canvas but can't delete the same on double click.`
var canvas,
context, shapes,
dragging = false, draggingtoMove = false,
dragStartLocation,dragEndLocation,
snapshot;
var numShapes;
function initiate() {
numShapes = 100;
shapes = [];
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
canvas.addEventListener('mousedown', dragStart, false);
canvas.addEventListener('mousemove', drag, false);
canvas.addEventListener('mouseup', dragStop, false);
canvas.addEventListener('dblclick', dblclickerase);
}
function dblclickerase(evt)
{
var i;
//We are going to pay attention to the layering order of the objects so that if a mouse down occurs over more than object,
//only the topmost one will be dragged.
var highestIndex = -1;
//getting mouse position correctly, being mindful of resizing that may have occured in the browser:
var bRect = canvas.getBoundingClientRect();
mouseX = (evt.clientX - bRect.left)*(canvas.width/bRect.width);
mouseY = (evt.clientY - bRect.top)*(canvas.height/bRect.height);
//find which shape was clicked
for (i=0; i < shapes.length; i++) {
if (hitTest(shapes[i], mouseX, mouseY)) {
//draggingtoMove = true;
if (i > highestIndex) {
// here i want to delete the circle on double click but not getting logic, I can get mouse location but how to select the circle and delete it
}
}
}
}
function getCanvasCoordinates(event) {
var x = event.clientX - canvas.getBoundingClientRect().left,
y = event.clientY - canvas.getBoundingClientRect().top;
return {
x: x,
y: y
};
}
function takeSnapshot() {
snapshot = context.getImageData(0, 0, canvas.width, canvas.height);
}
function restoreSnapshot() {
context.putImageData(snapshot, 0, 0);
}
function draw(position) {
var radius = Math.sqrt(Math.pow((dragStartLocation.x - position.x), 2) + Math.pow((dragStartLocation.y - position.y), 2));
var i=0;
var tempX;
var tempY;
var tempRad;
var tempR;
var tempG;
var tempB;
var tempColor;
tempRad = radius;
tempX = dragStartLocation.x;
tempY = dragStartLocation.y;
tempColor = getRndColor();
tempShape = {x:tempX, y:tempY, rad:tempRad, color:tempColor};
shapes.push(tempShape);
context.beginPath();
context.arc(tempX, tempY, tempRad, 0, 2*Math.PI, false);
//context.closePath();
context.fillStyle = tempColor;
context.fill();
i++;
}
function dragStart(evt) {
dragging = true;
//if (dragging == true) {
dragStartLocation = getCanvasCoordinates(evt);
takeSnapshot();
//}
}
function hitTest(shape,mx,my) {
var dx;
var dy;
dx = mx - shape.x;
dy = my - shape.y;
//a "hit" will be registered if the distance away from the center is less than the radius of the circular object
return (dx*dx + dy*dy < shape.rad*shape.rad);
}
function drag(event) {
var position;
if (dragging === true) {
restoreSnapshot();
position = getCanvasCoordinates(event);
draw(position);
}
}
function dragStop(event) {
dragging = false;
restoreSnapshot();
var position = getCanvasCoordinates(event);
dragEndLocation = getCanvasCoordinates(event);
draw(position);
}
function getRndColor() {
var r = 255 * Math.random() | 0,
g = 255 * Math.random() | 0,
b = 255 * Math.random() | 0;
return 'rgb(' + r + ',' + g + ',' + b + ')';
}
function eraseCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
addEventListener("load",initiate);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<canvas id="canvas" width="1020" height="640"></canvas>
<button onclick="eraseCanvas()" style="float: right;">Reset</button>
</body>
</html>
My question is how to delete the circle when double click on same, I
added 'dblClick' eventListener but still I am only able to perform the 'clearRect'
which will only clear the rectangle from start and end location which is little odd. Another thing I can't change the color to white which will not be valid.point as if my circle overlaps another will look odd.
You can't delete what you draw on the canvas like that. Once it's drawn on the canvas, it stays there and you have no way to access it except to read the pixel data - but that won't solve your problem because you can have overlapping circles of the same color.
To solve the issue, you must keep track of drawn circles, and redraw the full canvas every time it's needed (when adding a new circle, removing an old one, etc.). That way, when you want to delete a circle, you'd simply remove it from the list of circles (a simple array would work). But the important thing is that you need to clear and redraw the full canvas.
Summary: while having your canvas constantly redrawn (either on every tick or when a user interaction happens), your click'n'drag function should only be adding the circle to the circle list (specifying data like x, y, radius, color), while double-clicking a circle would look up that circle in the list, and remove it.

how can I put multiple objects on the same canvas?

i'm creating a web page where you dynamically draw multiple rectangles. I can draw the single object, but once I tried to draw another one, the previous one is gone away. I tried to save the state using save() and restore(), and it seems that I can't put it here. Isn't it logical that save method is put in the mouseup and restore method is called in the mousedown event? Any help or advice will be appreciated.
const canvas = document.getElementById("circle"),
ctx = canvas.getContext("2d"),
circle = {},
drag = false,
circleMade = false,
mouseMoved = false;
function draw() {
ctx.beginPath();
ctx.arc(circle.X, circle.Y, circle.radius, 0, 2.0 * Math.PI);
ctx.stroke();
}
function mouseDown(e) {
ctx.restore();
circle.startX = e.pageX - this.offsetLeft;
circle.startY = e.pageY - this.offsetTop;
circle.X = circle.startX;
circle.Y = circle.startY;
if (!circleMade) {
circle.radius = 0;
}
drag = true;
}
function mouseUp() {
drag = false;
circleMade = true;
if (!mouseMoved) {
circle = {};
circleMade = false;
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
mouseMoved = false;
ctx.save();
}
function mouseMove(e) {
if (drag) {
mouseMoved = true;
circle.X = e.pageX - this.offsetLeft;
circle.Y = e.pageY - this.offsetTop;
if (!circleMade) {
circle.radius = Math.sqrt(Math.pow((circle.X - circle.startX), 2) + Math.pow((circle.Y - circle.startY), 2));
}
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();
you need to save the information about what you are drawing in a separate object, every time you make a draw to the canvas you will wipe and redraw the new object.
so when you clearRect and then draw you are clearing and then drawing a fresh one but the old ones are being left behind. A good example:
var SavedCircles = [];
var circleInfo = function()
{
this.x = 0;
this.y = 0;
this.startX = 0;
this.startY = 0;
this.radius = 0;
}
circle = {};
function draw()
{
for(var x=0;x<SavedCircles.length;x++)
{
ctx.beginPath();
ctx.arc(SavedCircles[x].X, SavedCircles[x].Y, SavedCircles[x].radius, 0, 2.0 * Math.PI);
ctx.stroke();
}
}
function mouseDown()
{
circle = new circleInfo();
}
function mouseUp()
{
SavedCircles.push(circle);
}
function mouseMove()
{
draw();
}
so you can get rid of save and restore, also its much faster to clear a canvas simply by:
canvas.width = canvas.width;
this should help you keep all circles ever drawn. fill in the rest with your code.

Html5-canvas- How to remove space between the point I click and the draw point

please see the image below for better understanding what I mean :
http://8pic.ir/images/c6kzf0n0eu1v81sv3lit.jpg
as you can see, I scrolled down and when I click on canvas to point a position , it gives space between the point I click and the point it draw the line .
this is my code:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw,ch;
var $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var nameimageis =1;
// set some canvas styles
ctx.strokeStyle='black';
// an array to hold user's click-points that define the clipping area
var points=[];
// load the image
var img=new Image();
img.crossOrigin='anonymous';
img.onload=start;
img.src="http://localhost/image/D0D70A02A7_166.18K_{}_6458.JPG";
function start(){
// resize canvas to fit the img
cw=canvas.width=img.width;
ch=canvas.height=img.height;
// draw the image at 25% opacity
drawImage(1);
// listen for mousedown and button clicks
$('#canvas').mousedown(function(e){handleMouseDown(e);});
$('#reset').click(function(){ points.length=0; drawImage(1); });
}
rightclick = function(e) {
e.preventDefault();
if(!e.offsetX) {
e.offsetX = (e.pageX - $(e.target).offset().left);
e.offsetY = (e.pageY - $(e.target).offset().top);
}
var x = e.offsetX, y = e.offsetY;
for (var i = 0; i < points.length; i+=2) {
dis = Math.sqrt(Math.pow(x - points[i], 2) + Math.pow(y - points[i+1], 2));
if ( dis < 6 ) {
points.splice(i, 2);
draw();
record();
return false;
}
}
return false;
};
function handleMouseDown(e){
// tell the browser that we're handling this event
e.preventDefault();
e.stopPropagation();
// calculate mouseX & mouseY
mx=parseInt(e.clientX-offsetX);
my=parseInt(e.clientY-offsetY);
// push the clicked point to the points[] array
points.push({x:mx,y:my});
// show the user an outline of their current clipping path
outlineIt();
// if the user clicked back in the original circle
// then complete the clip
/*if(points.length>1){
var dx=mx-points[0].x;
var dy=my-points[0].y;
if(dx*dx+dy*dy<10*10){
clipIt();
}
}*/
}
// redraw the image at the specified opacity
function drawImage(alpha){
ctx.clearRect(0,0,cw,ch);
ctx.globalAlpha=alpha;
ctx.drawImage(img,0,0);
ctx.globalAlpha=1.00;
}
// show the current potential clipping path
function outlineIt(){
drawImage(1);
ctx.beginPath();
ctx.moveTo(points[0].x,points[0].y);
for(var i=0;i<points.length;i++){
ctx.lineTo(points[i].x,points[i].y);
}
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.arc(points[0].x,points[0].y,10,0,Math.PI*2);
ctx.closePath();
ctx.stroke();
}
How can I remove this space and point the right position every where I clicked?
It's because you are using e.clientY in function handleMouseDown. clientX/Y is relative to the viewport, not the document. Try use e.pageX/Y, which are relative to the document content.
More details in this question.

JavaScript - Canvas Drawing - Script Doesn't Work

I wrote a very simple JavaScript that uses the HTML5 canvas. When the user clicks their mouse on the canvas the script gets their mouse coordinates, then when they move their mouse while holding it down it draws a line, this repeats until they let up on the mouse. But it does not work and I have no idea why? Thanks in advance for your help.
<body>
<canvas id="myCanvas" width="500" height="500" style="border:1px solid #000000;">
</canvas>
<script>
// Canvas link
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
// Variables
var x1;
var y2;
var isPressed = false;
// Event listeners
context.addEventListener('mousedown', functionMouseDown, false);
context.addEventListener('mousemove', functionMouseMove, false);
context.addEventListener('mouseup', functionMouseUp, false);
function functionMouseDown() {
// Get coordinates
x1 = mousePos.x;
y1 = mousePos.y;
isPressed = true;
}
function functionMouseMove() {
// If mouse is down and moved start drawing line
if (isPressed == true) {
drawLine();
}
}
function functionMouseUp() {
// Stop drawing line
isPressed = false;
}
function drawLine() {
// Draw line
context.moveTo(x1,y1);
context.lineTo(x,y);
context.stroke();
// Set start coordinates to current coordinates
x1 = x;
y1 = y;
}
</script>
</body>
</html>
There are several problems here. You need to get the mouse position, which is not simply stored in mousePos.x/y. You get through the mouse move event, passed as the first param to the function which is added as the listener for mousemove, mousedown, mouseup. Here is how I fixed it
function functionMouseDown(e) {
// Get coordinates
x1 = e.clientX
y1 = e.clientY;
isPressed = true;
}
function functionMouseMove(e) {
// If mouse is down and moved start drawing line
if (isPressed == true) {
drawLine(e);
}
}
function functionMouseUp() {
// Stop drawing line
isPressed = false;
}
function drawLine(e) {
// Draw line
var x = e.clientX;
var y = e.clientY;
context.moveTo(x1,y1);
context.lineTo(x,y);
context.stroke();
// Set start coordinates to current coordinates
x1 = x;
y1 = y;
}

Categories