I'm creating a canvas with a save and reset button. the canvas supports free draw and is ment for autographs.
although I can't get the reset button to work, the save button works. Code snippet HTML:
<div>
<canvas id="theCanvas" width="300" height="150" style="-ms-touch-action: none; border: solid 1px #999"></canvas>
<div class="btn-group">
<button onclick="resetCanvas();" class="btn btn-danger">Reset</button>
<button onclick="saveCanvas();" class="btn btn-primary">Opslaan</button>
</div>
</div>
code snippet javascript:
var canvas, topmenu, context, touches = [], isWriting = false, lastContactPoint, currentTouchId;
var requestAnimFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
function draw() {
if (context) {
context.fillStyle = '#FFF';
context.fillRect(0, 0, canvas.width, canvas.height);
var i;
for (i = 0; i < touches.length; i++) {
drawSegment(touches[i]);
}
}
requestAnimFrame(draw);
}
function drawSegment(segment) {
var i, firstTouch = true;
context.beginPath();
for (i = 0; i < segment.length; i++) {
var touch = segment[i];
if (firstTouch) {
firstTouch = false;
context.beginPath();
context.moveTo(touch.x, touch.y);
continue;
}
context.lineTo(touch.x, touch.y);
}
context.strokeStyle = '#000';
context.lineWidth = 3;
context.stroke();
context.closePath();
}
function addTouch(position) {
var touchArray = touches[touches.length - 1];
touchArray.push(position);
}
requestAnimFrame(function () {
draw();
});
function load() {
topmenu = document.getElementsByClassName("navbar-fixed-top")[0]
canvas = document.getElementById('theCanvas');
context = canvas.getContext('2d');
canvas.addEventListener('touchstart', function (evt) {
evt.preventDefault();
currentTouchId = evt.touches[0].identifier;
touches.push([]);
position = getPositionFromTarget(evt.touches[0], evt.touches[0].target);
addTouch(position);
});
canvas.addEventListener('touchmove', function (evt) {
evt.preventDefault();
var i, position;
for (i = 0; i < evt.changedTouches.length; i++) {
if (evt.changedTouches[i].identifier !== currentTouchId)
continue;
position = getPositionFromTarget(evt.changedTouches[i], evt.changedTouches[i].target);
addTouch(position);
}
});
if (window.navigator.msPointerEnabled) {
canvas.addEventListener('MSPointerDown', function (evt) {
if (currentTouchId)
return;
currentTouchId = evt.pointerId;
touches.push([]);
var position = getPositionFromTarget(evt, evt.target);
addTouch(position);
});
canvas.addEventListener('MSPointerMove', function (evt) {
if (evt.pointerId !== currentTouchId)
return;
var position = getPositionFromTarget(evt, evt.target);
addTouch(position);
});
canvas.addEventListener('MSPointerUp', function (evt) {
currentTouchId = undefined;
});
}
else {
canvas.addEventListener('mousedown', function (evt) {
var position = getPositionFromTarget(evt, evt.target);
touches.push([]);
addTouch(position);
isWriting = true;
});
canvas.addEventListener('mousemove', function (evt) {
if (isWriting) {
var position = getPositionFromTarget(evt, evt.target);
addTouch(position);
}
});
canvas.addEventListener('mouseup', function (evt) {
var position = getPositionFromTarget(evt, evt.target);
addTouch(position);
isWriting = false;
});
}
}
function getPositionFromTarget(evt, target) {
return {
y: evt.pageY - (target.offsetTop + (topmenu.clientHeight - 3)),
x: evt.pageX - target.offsetLeft
};
}
window.addEventListener('load', load);
function resetCanvas() {
context.beginPath();
context.clearRect(0, 0, canvas.width, canvas.height);
context.closePath();
}
I've read some solutions with beginPath and closePath and tried it in the function resetCanvas and in draw segment.
then I tried to remove the listeners from the canvas, maybe that could be the reason... although after I remove the listeners using:
//var new_element = canvas.cloneNode(true);
//canvas.parentNode.replaceChild(new_element, canvas);
I are not able to draw again, what am I missing?
Instead of drawing a white rectangle, use clearRect() method to clear / reset the canvas.
also, you need to reset the touches array (as the saved segments are being drawn in a loop).
function resetCanvas() {
touches = []; //reset 'touches' array
context.clearRect(0, 0, canvas.width, canvas.height); //clear canvas
}
Related
I am trying to make an 'undo' action like Ctrl + Z.
I made a simple canvas paint example to make it easier to understand what I would like. When the user moves the mouse without releasing mouse1, something will be drawn on the canvas. Then, when they stop pressing mouse1, the drawing ends. The Ctrl + Z shortcut will undo these drawings.
Here is the code:
//var
const canvas = document.getElementById('canvas');
const cC = canvas.getContext('2d');
//trigger for write or not
var pressedQ = false;
//
function getMousePosition(evt) {
var rect = canvas.getBoundingClientRect();
var root = document.documentElement;
var mouseX = evt.clientX - rect.left - root.scrollLeft;
var mouseY = evt.clientY - rect.top - root.scrollTop;
return {
x: mouseX,
y: mouseY
};
}
function writeCircle(posX, posY, size, color) {
cC.fillStyle = 'black';
cC.beginPath();
cC.arc(posX, posY, size, 0, Math.PI*2, true);
cC.fill();
}
function pencil(evt) {
if (pressedQ == true) {
var mousePos = getMousePosition(evt);
writeCircle(mousePos.x, mousePos.y, 50);
}
else{}
}
function activate(textmode, evt) {
pressedQ = true;
console.log('start');
}
function deactivate() {
pressedQ = false;
console.log('finish');
}
window.onload = function() {
cC.clearRect(0, 0, canvas.width, canvas.height);
canvas.addEventListener('mousedown', activate);
canvas.addEventListener('mousemove', pencil);
canvas.addEventListener('mouseup', deactivate);
}
<canvas id="canvas" width="700" height="490"></canvas>
Thanks!
Note: I cant understand ES2015+ syntax
What you're looking for is the command design pattern. Since you're using functions here, you just need to store the function name and its parameters. Then, you can use that data to call the function again later. The following example isn't perfect, but it should demonstrate the basic idea. (I tried to avoid any JavaScript syntax that was added after the 2015 update)
var canvas = document.getElementById('canvas');
var cC = canvas.getContext('2d');
var pressedQ = false; //trigger for write or not
var commands = [];
var commandTypes = {
drawCircle: function (posX, posY, size, color) {
cC.fillStyle = 'black';
cC.beginPath();
cC.arc(posX, posY, size, 0, Math.PI * 2, true);
cC.fill();
}
};
function execute() {
var commandType = arguments[0];
var data = Array.prototype.slice.call(arguments, 1);
if (!commandTypes.hasOwnProperty(commandType))
throw new Error(commandType + ' is not a real command');
commandTypes[commandType].apply(null, data);
}
function pushAndExecute() {
commands.push(arguments);
execute.apply(null, arguments);
}
function getMousePosition(evt) {
var rect = canvas.getBoundingClientRect();
var root = document.documentElement;
return {
x: evt.offsetX - rect.left - root.scrollLeft,
y: evt.offsetY - rect.top - root.scrollTop
};
}
function pencil(evt) {
if (!pressedQ) return;
var mousePos = getMousePosition(evt);
pushAndExecute('drawCircle', mousePos.x, mousePos.y, 50);
}
function activate(evt) {
pressedQ = true;
// console.log('start');
pencil(evt);
}
function deactivate() {
pressedQ = false;
// console.log('finish');
}
function handleKeys(evt) {
if (evt.ctrlKey && evt.key === 'z') {
// console.log('undo');
// Remove the most recent command from the list
commands.splice(-1, 1);
// Clear canvas
cC.clearRect(0, 0, canvas.width, canvas.height);
// Re-play all commands (re-draw canvas from scratch)
commands.forEach(function (command) {
execute.apply(null, command);
});
}
}
window.onload = function() {
cC.clearRect(0, 0, canvas.width, canvas.height);
canvas.addEventListener('mousedown', activate);
canvas.addEventListener('mousemove', pencil);
canvas.addEventListener('mouseup', deactivate);
window.addEventListener('keydown', handleKeys);
}
<canvas id="canvas" width="700" height="490"></canvas>
You might see that this is my first post so excuse any beginner mistakes using stackoverflow.
I'm currently working on a floor plan web app where you can simply draw lines to create the floor plan of your housing.
The wanted effect is:
When clicking once the user draws a temporary line where the start point X is the clicked point and the target point Z is the mouse which the user can move around.
I'm currently using canvas for this effect but somehow the line is invisible or just not there. I've tried some debugging which brought me here.
This is the current code:
function drawLineXY(fromXY, toXY) {
if (!lineElem) {
lineElem = document.createElement('canvas');
lineElem.style.position = "absolute";
lineElem.style.zIndex = 100;
document.body.appendChild(lineElem);
console.log("Added line element");
}
var leftpoint, rightpoint;
if (fromXY.x < toXY.x) {
leftpoint = fromXY;
rightpoint = toXY;
} else {
leftpoint = toXY;
rightpoint = fromXY;
}
var lineWidthPix = 4;
var gutterPix = 0;
var origin = {
x: leftpoint.x - gutterPix,
y: Math.min(fromXY.y, toXY.y) - gutterPix
};
lineElem.width = "1000px";
lineElem.height = "1000px";
lineElem.style.left = "0px";
lineElem.style.top = "0px";
var ctx = lineElem.getContext('2d');
// Use the identity matrix while clearing the canvas
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, lineElem.width, lineElem.height);
ctx.restore();
ctx.lineWidth = 4;
ctx.strokeStyle = '#09f';
ctx.beginPath();
ctx.moveTo(fromXY.x - origin.x, fromXY.y - origin.y);
ctx.lineTo(toXY.x - origin.x, toXY.y - origin.y);
ctx.stroke();
console.log("drawing line..");
}
function moveHandler(evt) {
var startCentre, startBounds;
var targets = [];
if (clicked.length === 2) {
targets = clicked;
} else if (clicked.length === 1) {
targets.push(clicked[0]);
if (typeof hoverElement !== 'undefined') {
targets.push(hoverElement);
}
}
if (targets.length == 2) {
var start = {
x: targets[0],
y: targets[0]
};
var end = {
x: targets[1],
y: targets[1]
};
drawLineXY(start, end);
} else if (targets.length == 1) {
var start = {
x: targets[0],
y: targets[0]
};
drawLineXY(start, {
x: evt.clientX,
y: evt.clientY
});
}
};
function clickHandler(e) {
if (clicked.length == 2) {
clicked = [];
}
clicked.push(e.target);
};
document.onclick = clickHandler;
document.onmousemove = moveHandler;
As you can see in drawLineXY's last line I've made a debug console log "drawing line"
This works as I move the mouse around. Like it should.
But there is no line, does someone has help?
PS: #canvas is specified in style.css.
I created a very basic example of probably what you are trying to achieve:
let c, ctx, fromXY, toXY;
window.onload = function(){
document.onclick = clickHandler;
document.onmousemove = moveHandler;
c = document.getElementById("myCanvas");
ctx = c.getContext("2d");
reset();
}
function draw(){
clear();
ctx.beginPath();
ctx.moveTo(fromXY.x, fromXY.y);
ctx.lineTo(toXY.x, toXY.y);
ctx.stroke();
ctx.closePath();
}
function clear(){
ctx.clearRect(0, 0, c.width, c.height);
}
function reset() {
fromXY = {};
toXY = {};
}
function moveHandler(e) {
if(typeof fromXY.x !== "undefined"){
toXY.x = e.clientX;
toXY.y = e.clientY;
draw();
}
}
function clickHandler(e) {
if(typeof fromXY.x === "undefined"){
fromXY.x = e.clientX;
fromXY.y = e.clientY;
}else{
reset();
}
}
<canvas id="myCanvas" height="500" width="500"></canvas>
You can set line options in the draw() function, and if you want the lines to persist, you would save their fromXY and toXY in an array and redraw them as well.
I'm using this code, and it works with charm - It draws a polygon (with canvas) on a given picture, however I'm struggling to modify code, so that it would enable me to draw multiple polygons instead of just one.
I'm a noob to js and haven't found yet anything that might solve it, I'd appreciate any help/hint in some direction.
Code:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="main.css">
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.js"></script>
<script>
//radius of click around the first point to close the draw
var END_CLICK_RADIUS = 15;
//the max number of points of your polygon
var MAX_POINTS = 8;
var mouseX = 0;
var mouseY = 0;
var isStarted = false;
var points = null;
var canvas = null;
window.onload = function() {
background = document.getElementById('justanimage');
//initializing canvas and draw color
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
changeColor("blue");
image = new Image();
image.onload = function() {
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
};
image.src = 'justanimage.gif';
canvas.addEventListener("click", function(e) {
var x = e.clientX-canvas.offsetLeft;
var y = e.clientY-canvas.offsetTop;
if(isStarted) {
//drawing the next line, and closing the polygon if needed
if(Math.abs(x - points[0].x) < END_CLICK_RADIUS && Math.abs(y - points[0].y) < END_CLICK_RADIUS) {
isStarted = false;
} else {
points[points.length] = new Point(x, y);
if(points.length >= MAX_POINTS) {
isStarted = false;
}
}
} else if(points == null) {
//opening the polygon
points = new Array();
points[0] = new Point(x, y);
isStarted = true;
}
}, false);
//we just save the location of the mouse
canvas.addEventListener("mousemove", function(e) {
mouseX = e.clientX - canvas.offsetLeft;
mouseY = e.clientY - canvas.offsetTop;
}, false);
//refresh time
setInterval("draw();", 5);
}
//object representing a point
function Point(x, y) {
this.x = x;
this.y = y;
}
//resets the application
function reset() {
isStarted = false;
points = null;
document.getElementById("coordinates").innerHTML = " ";
}
//displays coordinates of the the point list
function save() {
if(points == null) {
alert("No picture!");
} else {
var s = "";
for(var a in points) {
//inversing y axis by (canvas.height - points[a].y)
s += "(" + points[a].x + "," + (canvas.height - points[a].y) + ")\n";
}
document.getElementById("coordinates").innerHTML = s + '\n';
}
}
//draws the current shape
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
if(points != null && points.length > 0) {
ctx.moveTo(points[0].x, points[0].y);
for(i = 1 ; i < points.length ; i++) {
ctx.lineTo(points[i].x, points[i].y);
}
if(isStarted) {
ctx.lineTo(mouseX, mouseY);
} else {
ctx.lineTo(points[0].x, points[0].y);
}
}
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
ctx.stroke();
}
</script>
</head>
<body>
<div id="outer">
<canvas id="canvas" width=300 height=300; ></canvas>
</div>
<p id="coordinates"> </p>
<input type="button" value="Save" onclick="save();" />
<input type="button" value="Reset" onclick="reset();" />
</body>
</html>
Basically this solution adds a new array polygons, which keeps all polygons. The points array is now included in the polygons.
var polygons = [];
window.onload = function () {
// ...
canvas.addEventListener("click", function (e) {
// ...
if (isStarted) {
//drawing the next line, and closing the polygon if needed
if (Math.abs(x - polygons[polygons.length - 1][0].x) < END_CLICK_RADIUS && Math.abs(y - polygons[polygons.length - 1][0].y) < END_CLICK_RADIUS) {
isStarted = false;
} else {
polygons[polygons.length - 1].push(new Point(x, y));
if (polygons[polygons.length - 1].length >= MAX_POINTS) {
isStarted = false;
}
}
} else {
//opening the polygon
polygons.push([new Point(x, y)]);
isStarted = true;
}
}, false);
// ...
}
function draw() {
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
polygons.forEach(function (points, i) {
ctx.beginPath();
points.forEach(function (p, j) {
if (j) {
ctx.lineTo(p.x, p.y);
} else {
ctx.moveTo(p.x, p.y);
}
});
if (i + 1 === polygons.length && isStarted) { // just the last one
ctx.lineTo(mouseX, mouseY);
} else {
ctx.lineTo(points[0].x, points[0].y);
}
ctx.stroke();
});
}
(Another solution might be to save the image with the last polygon and use it again for the new polygon.)
Working example:
//radius of click around the first point to close the draw
var END_CLICK_RADIUS = 15;
//the max number of points of your polygon
var MAX_POINTS = 8;
var mouseX = 0;
var mouseY = 0;
var isStarted = false;
var polygons = [];
var canvas = null;
var ctx;
var image;
window.onload = function () {
var background = document.getElementById('justanimage');
//initializing canvas and draw color
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
//changeColor("blue"); // <-- is missing!
image = new Image();
image.onload = function () {
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
};
image.src = 'http://lorempixel.com/10/10/';
canvas.addEventListener("click", function (e) {
var x = e.clientX - canvas.offsetLeft;
var y = e.clientY - canvas.offsetTop;
if (isStarted) {
//drawing the next line, and closing the polygon if needed
if (Math.abs(x - polygons[polygons.length - 1][0].x) < END_CLICK_RADIUS && Math.abs(y - polygons[polygons.length - 1][0].y) < END_CLICK_RADIUS) {
isStarted = false;
} else {
polygons[polygons.length - 1].push(new Point(x, y));
if (polygons[polygons.length - 1].length >= MAX_POINTS) {
isStarted = false;
}
}
} else {
//opening the polygon
polygons.push([new Point(x, y)]);
isStarted = true;
}
}, false);
//we just save the location of the mouse
canvas.addEventListener("mousemove", function (e) {
mouseX = e.clientX - canvas.offsetLeft;
mouseY = e.clientY - canvas.offsetTop;
}, false);
//refresh time
setInterval("draw();", 5);
}
//object representing a point
function Point(x, y) {
this.x = x;
this.y = y;
}
//resets the application
function reset() {
isStarted = false;
points = null;
document.getElementById("coordinates").innerHTML = " ";
}
//draws the current shape
function draw() {
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
polygons.forEach(function (points, i) {
ctx.beginPath();
points.forEach(function (p, j) {
if (j) {
ctx.lineTo(p.x, p.y);
} else {
ctx.moveTo(p.x, p.y);
}
});
if (i + 1 === polygons.length && isStarted) { // just the last one
ctx.lineTo(mouseX, mouseY);
} else {
ctx.lineTo(points[0].x, points[0].y);
}
ctx.stroke();
});
}
<canvas id="canvas" width="500" height="500"></canvas>
<img id="justanimage" />
I am trying to draw polygons(lets say 4 sided) on a canvas using mouse click and move events.
Click on canvas the moveTo(this point).
Now move the cursor a lineTo(the current point) but not intermediate point. Line should keep moving with mousemove and should be draw to the canvas only once clicked.
After fourth click(or any x) the polygon should closepath();
var pressed = false;
function myfunc1(e){
context.beginPath();
context.arc(e.clientX, e.clientY, radius, 0, Math.PI*2);
context.fill();
context.beginPath();
context.moveTo(e.clientX,e.clientY);
pressed = true;
}
function myfunc2(e){
if(pressed ===true){
context.lineTo(e.clientX,e.clientY);
context.stroke();
}
}
canvas.addEventListener('click',myfunc1);
canvas.addEventListener('mousemove',myfunc2);
I wrote this, but i don't want the intermediate lines
What you need is a stack. Don't think of drawing lines. Think of storing all your points of click in an array. And when you have clicked 4 times, draw the polygon (assuming that is what you want). Something like this:
var stack = [];
myfunc1(e){
stack.push(e.clientX, e.clientY);
if(stack.length == 4)
actuallyDraw();
}
var actuallyDraw(){
//take the 4 points in stack and draw the polygon
//clearing the stack for the next polygon
stack.length = 0;
}
canvas.addEventListener('click', myfunc1);
Use below code it will help you to solve your problem.
Click to assign polygon vertices point
<button id=done>Click when done assigning points</button>
<canvas id="canvas" width=450 height=450></canvas>
var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
context.lineWidth=2;
context.strokeStyle='blue';
var coordinates = [];
var isDone=false;
$('#done').click(function(){
isDone=true;
});
$("#canvas").mousedown(function(e){handleMouseDown(e);});
function handleMouseDown(e){
if(isDone || coordinates.length>10){return;}
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
coordinates.push({x:mouseX,y:mouseY});
drawPolygon();
}
function drawPolygon(){
context.clearRect(0,0,cw,ch);
context.beginPath();
context.moveTo(coordinates[0].x, coordinates[0].y);
for(index=1; index<coordinates.length;index++) {
context.lineTo(coordinates[index].x, coordinates[index].y);
}
context.closePath();
context.stroke();
}
I created an array(cords[]) which holds the coordinates of the polygon i am drawing and push them to another array (polygons[]) if the current polygon is completed. Then i can clear the canvas when required and redraw the polygons from polygon[]
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = document.getElementById("myimg");
ctx.drawImage(img, 0, 0);
var canvasOffset = $("#canvas").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var polygons = [];
var cords = [];
var start = false;
var control = false;
var clicks = 0;
ctx.strokeStyle = "orange";
ctx.lineWidth = 1;
$("#canvas").mousedown(function(e) {
handleMouseDown(e);
});
$("#canvas").mousemove(function(e) {
handleMouseMove(e);
});
function handleMouseDown(e) {
start = false;
clicks = clicks + 1;
var mouseX = parseInt(e.clientX - offsetX);
var mouseY = parseInt(e.clientY - offsetY);
cords.push([mouseX, mouseY]);
console.log(cords);
clearanddraw();
if (clicks % 4 === 0) {
return;
}
start = true;
}
function handleMouseMove(e) {
if (!start) {
return;
}
canvasclear();
var mouseX = parseInt(e.clientX - offsetX);
var mouseY = parseInt(e.clientY - offsetY);
ctx.beginPath();
ctx.moveTo(cords[clicks - 1][0], cords[clicks - 1][1]);
ctx.lineTo(mouseX, mouseY);
ctx.stroke();
}
function canvasclear() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(myimg, 0, 0);
drawOtherPol();
ctx.beginPath();
ctx.moveTo(cords[0][0], cords[0][1]);
for (var i = 0; i < clicks - 1; i++) {
ctx.lineTo(cords[i + 1][0], cords[i + 1][1]);
//alert("redrwan");
}
ctx.stroke();
return;
}
function clearanddraw() {
if (clicks > 1) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(myimg, 0, 0);
drawOtherPol();
ctx.beginPath();
ctx.moveTo(cords[0][0], cords[0][1]);
for (var i = 0; i < clicks - 1; i++) {
ctx.lineTo(cords[i + 1][0], cords[i + 1][1]);
}
if (clicks < 4) {
ctx.stroke();
}
if (clicks === 4) {
ctx.closePath();
ctx.stroke();
savepolygon();
cords = [];
clicks = 0;
return;
}
}
start = true;
}
function savepolygon() {
polygons.push(cords);
console.log(polygons);
return
}
function drawOtherPol() {
if (polygons.length === 0) {
return;
} else {
for (var i = 0; i < polygons.length; i++) {
ctx.beginPath();
ctx.moveTo(polygons[i][0][0], polygons[i][0][1]);
ctx.lineTo(polygons[i][1][0], polygons[i][1][1]);
ctx.lineTo(polygons[i][2][0], polygons[i][2][1]);
ctx.lineTo(polygons[i][3][0], polygons[i][3][1]);
ctx.closePath();
ctx.stroke();
}
return;
}
}
i need to remove unconnected points when i mouseout from canvas. I just draw lines when mousemove using moveTo and LineTo. when mouseout from canvas have to omit the unconnected points.
Here is code for jquery:
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript">
$(function() {
var canvas = $('#canvas');
var context = canvas.get(0).getContext("2d");
var clicked = false;
var b=0;
var storedLines = [];
var storedLine = {};
var mouse = {
x: -1,
y: -1
}
var parentOffset = $('#canvas').offset();
canvas.click(function(e) {
if (b==1)
{
$(this).unbind(e);
}
else
{
clicked = true;
mouse.x = e.pageX - parentOffset.left;
mouse.y = e.pageY - parentOffset.top;
context.moveTo(mouse.x, mouse.y);
if (clicked) {
storedLines.push({
startX: storedLine.startX,
startY: storedLine.startY,
endX: mouse.x,
endY: mouse.y
});
}
storedLine.startX = mouse.x;
storedLine.startY = mouse.y;
$(this).mousemove(function(k) {
context.clearRect(0, 0, 960, 500);
context.beginPath();
context.strokeStyle = "blue";
for (var i = 0; i < storedLines.length; i++) {
var v = storedLines[i];
context.moveTo(v.startX, v.startY);
context.lineTo(v.endX, v.endY);
context.stroke();
}
context.moveTo(mouse.x, mouse.y);
context.lineTo(k.pageX - parentOffset.left, k.pageY - parentOffset.top);
context.stroke();
context.closePath();
});
}
});
$('#canvas').mouseout(function(e){
$(this).unbind("mousemove");
b=1;
});
});
HTML code:
<html>
<body>
<canvas id="canvas" width=600 height=600 ></canvas>
</body>
</html>
First thing to do is to clarify the code : Have one part that deals only with the mouse, and another part that deals only with the lines.
This way you will have a much better view on what will happen on each event.
I started a bit to clarify the code, you should even make a class handling lines (which will be very useful if you handle several of them).
jsbin is here : http://jsbin.com/eseTODo/2/edit?js,output
var canvas = $('#canvas');
var context = canvas.get(0).getContext("2d");
// -----------------------------------------
// Mouse
var clicked = false;
var onCanvas = false;
var mouse = {
x: -1,
y: -1
}
var parentOffset = $('#canvas').offset();
canvas.mousedown(function (e) {
clicked = true;
if (!onCanvas) return;
mouse.x = e.pageX - parentOffset.left;
mouse.y = e.pageY - parentOffset.top;
addPoint(mouse.x, mouse.y);
clearScreen();
drawLines();
});
canvas.mouseup(function (e) {
clicked = false;
if (!onCanvas) return;
});
canvas.mousemove(function (e) {
if (!onCanvas) return;
clearScreen();
drawLines();
drawPendingLine(e.pageX - parentOffset.left,
e.pageY - parentOffset.top);
});
canvas.mouseout(function (e) {
onCanvas = false;
clearScreen();
drawLines();
clearLines();
});
canvas.mouseenter(function (e) {
onCanvas = true;
});
// -----------------------------------------
// Lines
var storedLines = [];
var storedLine = {};
var startedALine = false;
function clearLines() {
storedLines.length = 0;
startedALine = false;
}
function addPoint(x, y) {
if (startedALine) {
storedLines.push({
startX: storedLine.startX,
startY: storedLine.startY,
endX: x,
endY: y
});
}
startedALine = true;
storedLine.startX = x;
storedLine.startY = y
}
function drawLines() {
context.strokeStyle = "blue";
if (!startedALine) return;
if (!storedLines.length) return;
for (var i = 0; i < storedLines.length; i++) {
var v = storedLines[i];
context.beginPath();
context.moveTo(v.startX, v.startY);
context.lineTo(v.endX, v.endY);
context.stroke();
context.closePath();
}
context.stroke();
}
function drawPendingLine(lastX, lastY) {
if (!startedALine) return;
context.beginPath();
context.strokeStyle = "green";
context.moveTo(storedLine.startX, storedLine.startY);
context.lineTo(lastX, lastY);
context.stroke();
context.closePath();
}
function clearScreen() {
context.clearRect(0, 0, 600, 600);
}
Can't you set a flag like
var hasLeftCanvas = false;
and set it to true when you leave the canvas?
canvas.onmouseleave = function() {
hasLeftCanvas = true;
}
and then, in your script:
$(this).mousemove(function(k) {
if(!hasLeftCanvas) {
context.clearRect(0, 0, 960, 500);
context.beginPath();
context.strokeStyle = "blue";
for (var i = 0; i < storedLines.length; i++) {
var v = storedLines[i];
context.moveTo(v.startX, v.startY);
context.lineTo(v.endX, v.endY);
context.stroke();
}
context.moveTo(mouse.x, mouse.y);
context.lineTo(k.pageX - parentOffset.left, k.pageY - parentOffset.top);
context.stroke();
context.closePath();
}
});
remember to set it back to false when the cursor re enters the canvas