How do I create a Ctrl+z event on the canvas? - javascript

I am trying to make an 'undo' action like Ctrl + Z.
But I really don't know how to make it.
This is my code. I want to add a ctrl+z event, but I don't know what to do.
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const modeBtn = document.querySelector("#mode-btn");
const CANVAS_WIDTH = 800;
const CANVAS_HEIGHT = 800;
canvas.width = CANVAS_WIDTH;
canvas.height = CANVAS_HEIGHT;
ctx.lineCap = "round";
let isPainting = false;
let isFilling = false;
function onMove(event) {
if (isPainting) {
ctx.lineTo(event.offsetX, event.offsetY);
ctx.stroke();
return;
}
ctx.moveTo(event.offsetX, event.offsetY);
}
function startPainting() {
isPainting = true;
}
function cancelPainting() {
isPainting = false;
ctx.beginPath();
}
function onModeClick() {
if (isFilling) {
isFilling = false;
} else {
isFilling = true;
}
}
function onCanvasClick() {
if (isFilling) {
ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
}
}
canvas.addEventListener("mousemove", onMove);
canvas.addEventListener("mousedown", startPainting);
canvas.addEventListener("mouseup", cancelPainting);
canvas.addEventListener("mouseleave", cancelPainting);
canvas.addEventListener("click", onCanvasClick);
modeBtn.addEventListener("click", onModeClick);
<canvas></canvas>
<div class="btns">
<button id="mode-btn">Draw</button>
</div>
<script src="app.js"></script>
I used split(-1,1), but it didn't work at all, or it was deleted completely, not undo.
I am a beginner. I don't know how to apply it. Help me, please.

For a beginner, the simplest approach you can take is to keep an array of the positions that you drew on in a stack, and during the undo operation, just pop those values and clear those positions on the canvas.
To listen for the ctrl+z keypress you can use something like this -
function onUndo() {
var evtobj = window.event ? event : e;
if (evtobj.keyCode == 90 && evtobj.ctrlKey) undo();
}
document.addEventListener("keydown", onUndo);
And to undo the operations, the simplest code could look something like this (note this basically the opposite of what you were doing during drawing) -
function undo() {
const color = ctx.strokeStyle;
ctx.strokeStyle = BG_COLOR;
if (actions.length === 0) {
ctx.strokeStyle = color;
return;
}
const action = actions.pop();
if (action.type === "move") {
ctx.lineTo(action.x, action.y);
ctx.stroke();
}
ctx.strokeStyle = color;
}
Here BG_COLOR is background color of your canvas
Also, this approach might work for now, but it would get difficult to manage and maintain as you add more kinds of drawing approaches to your canvas. To do this in a more maintainable way, I would suggest that you look into the memento pattern

Related

Javascript help handling mouseclick in canvas

I'm trying to get my inputhandler to work in Javascript.
What
In my Game.update I currently have this code:
this.Update = function() {
if (input.GetMousePressed()) {
console.log(input.GetMousePosition());
}
}
And this is my inputhandler:
function InputHandler(canvas) {
this.canvas = canvas;
this.mousePressed = false;
this.mouseDown = false;
this.mousePosition = new Position(0, 0);
this.GetMousePosition = function() {
return this.mousePosition;
}
this.SetMousePosition = function(event) {
var rect = this.canvas.getBoundingClientRect();
this.mousePosition = new Position(event.clientX - rect.left, event.clientY - rect.top);
}
this.GetMousePressed = function() {
return this.mousePressed;
}
this.canvas.onmousedown = function(event) {
input.mouseDown = true;
input.SetMousePosition(event);
}
this.canvas.onclick = function(event) {
input.mouseClicked = true;
input.SetMousePosition(event);
}
window.onmouseup = function(event) {
if (input.mouseDown == true) {
input.mousePressed = true;
input.mouseDown = false;
}
}
The first problem is that I dont know how to handle mousePressed and set it to false. Now it stays true forever.
I'm quite new to Javascript and I'm thankful for any change that would make this better or cleaner code or if what Im doing is bad practice.
I'm using addEventListener for normal button pressing and maybe I should for this to?
Not sure why you need mousepressed/mouseup and click events. The only difference between successful pressed/up and click is that click target should be the same element.
So I would either use the first option or the last but not both.
Your mousePressed flag is set to true because it gets assigned true value once you press the mouse. You need to reset it back to false at some point.
Usually, you don't even need this flag since you trigger whatever function you need inside mousepressed event. Not sure why you would save the information that this happened, do you use it somewhere else?
Also, yes using addEventListener would be better.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}
canvas {
position: absolute;
margin: auto;
left: 0;
right: 0;
border: solid 1px white;
border-radius: 10px;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">
var imageWidth = 180;
var imageHeight = 160;
var canvas = null;
var ctx = null;
var mouseDown = false;
var mouseX = 0;
var mouseY = 0;
var bounds = null;
function canvas_onmousedown(e) {
mouseDown = true;
}
function canvas_onmousemove(e) {
if (mouseDown) {
mouseX = e.clientX - bounds.left;
mouseY = e.clientY - bounds.top;
}
}
function canvas_onmouseup(e) {
mouseDown = false;
}
function loop() {
ctx.fillStyle = "gray";
ctx.fillRect(0,0,imageWidth,imageHeight);
if (mouseDown) {
ctx.fillStyle = "yellow";
} else {
ctx.fillStyle = "black";
}
ctx.fillRect(mouseX - 25,mouseY - 25,50,50);
requestAnimationFrame(loop);
}
window.onload = function() {
canvas = document.getElementById("canvas");
canvas.width = imageWidth;
canvas.height = imageHeight;
canvas.onmousedown = canvas_onmousedown;
canvas.onmousemove = canvas_onmousemove;
canvas.onmouseup = canvas_onmouseup;
ctx = canvas.getContext("2d");
bounds = canvas.getBoundingClientRect();
requestAnimationFrame(loop);
}
</script>
</body>
</html>

HTML5 Canvas - Keyboard keys do not respond

I'm trying to implement key input in my ping-pong game. The main point is that the up and down arrow keys don't work at all. My browser console doesn't display any errors messages.
Here is my code, this is WIP some Objects are not implemented yet
var playerBat = {
x: null,
y: null,
width: 20,
height: 80,
UP_DOWN: false,
DOWN_DOWN: false,
update: function() {
// Keyboard inputs
window.addEventListener('keydown', onKeyDown, false);
window.addEventListener('keyup', onKeyUp, false);
var key = {
UP: 38,
DOWN: 40
};
function onKeyDown(e) {
if (e.keyCode == 38)
this.UP_DOWN = true;
else if (e.keyCode == 40)
this.DOWN_DOWN = true;
}
function onKeyUp(e) {
if (e.keyCode == 38)
this.UP_DOWN = false;
else if (e.keyCode == 40)
this.DOWN_DOWN = false;
}
this.y = Math.max(Math.min(this.y, Canvas_H - this.height), 0); // Collide world bounds
},
render: function() {
ctx.fillStyle = '#000';
ctx.fillRect(this.x, this.y, this.width, this.height);
if (this.UP_DOWN)
this.playerBat.y -= 5;
else if (this.DOWN_DOWN)
this.playerBat.y += 5;
}
};
The events are firing, the problem is that you're adding them on each update. What you'll want to do it take the callbacks and the addEventListeners outside in a method such as addEvents, which should be called ONCE during initialization. Currently the huge amount of event handlers being triggered kills the page.
function addEvents() {
window.addEventListener('keydown', onKeyDown, false);
window.addEventListener('keyup', onKeyUp, false);
var key = {
UP: 38,
DOWN: 40
};
function onKeyDown(e) {
if (e.keyCode == key.UP) {
playerPaddle.UP_DOWN = true;
}
if (e.keyCode == key.DOWN) {
playerPaddle.DOWN_DOWN = true;
}
}
function onKeyUp(e) {
if (e.keyCode == key.UP) {
playerPaddle.UP_DOWN = false;
}
if (e.keyCode == 40) {
playerPaddle.DOWN_DOWN = key.DOWN;
}
}
}
After reviewing it further there are some other problems. First of all, the logic for actually changing the X and Y of the paddle should be within the update method (since that's what's usually used to change object properties), while the render method should simply draw the shapes and images using the object's updated properties.
Second, you're trying to access this.playerBat.y within the render method, however 'this' actually IS the playerBat. So in order to properly target the 'y' property you'd need to write this.y instead.
I also noticed that you've got a key map, with UP and DOWN keycodes defined, but don't actually use it, instead you use numbers. Maybe something you were planning on doing?
I reimplemented the code you have provided and added a init function to playerBat that attaches the event listeners for keydown and keyup events. I just kept the relevant bits and implemented objects as functions, but the concept should still be the applicable.
The callback function passed into addEventListener needs to bind this, otherwise the this value inside the callback (this.UP_DOWN and this.DOWN_DOWN) won't be the same as the this value in the enclosing scope; the one value you intended.
<canvas id='canvas' style="background:#839496">Your browser doesn't support The HTML5 Canvas</canvas>
<script>
var canvas = document.getElementById('canvas');
canvas.width = window.innerWidth-20;
canvas.height = window.innerHeight-20;
var ctx = canvas.getContext('2d');
var Canvas_W = Math.floor(canvas.width);
var Canvas_H = Math.floor(canvas.height);
/*
* Define a Player object.
*/
function PlayerBat(){
this.x = null;
this.y = null;
this.width = 20;
this.height = Canvas_H/3;
this.UP_DOWN = false;
this.DOWN_DOWN = false;
this.init = function() {
console.log('init');
// MUST bind `this`!
window.addEventListener('keydown', function(e){
console.log('keydown');
if (e.keyCode == 38) this.UP_DOWN = true;
else if (e.keyCode == 40) this.DOWN_DOWN = true;
}.bind(this), false);
// MUST bind `this`!
window.addEventListener('keyup', function(e){
console.log('keyUp')
if (e.keyCode == 38) this.UP_DOWN = false;
else if (e.keyCode == 40) this.DOWN_DOWN = false;
}.bind(this), false);
};
this.update = function() {
var key = {UP: 38, DOWN: 40};
this.y = Math.max(Math.min(this.y, Canvas_H - this.height), 0);
};
this.render = function() {
// Clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Redraw paddle
ctx.fillStyle = '#00F';
ctx.fillRect(this.x, this.y, this.width, this.height);
this.y = (this.UP_DOWN) ? this.y - 5 : ((this.DOWN_DOWN) ? this.y + 5 : this.y );
};
}
function GameRunner(){
// Create instance of player
var playerBat = new PlayerBat();
playerBat.init();
// Execute upon instantiation of GameRunner
(function () {
playerBat.x = playerBat.width;
playerBat.y = (Canvas_H - playerBat.height) / 2;
})();
function step() {
playerBat.update();
playerBat.render();
requestAnimationFrame(step);
}
// Public method. Start animation loop
this.start = function(){
requestAnimationFrame(step);
}
}
// Create GameRunner instance
var game = new GameRunner();
// Start game
game.start();
</script>

mouseclick event JavaScript doesn't work in Firefox

I made this piece of code for turning sound on/off in a game I'm making.
It works great with Google Chrome and IE. Proud as I was I gave the code to my friend who tried it on Firefox..
But he made me sad by saying it didn't work on Firefox...
I don't know why it doesn't work, can somebody tell me what's wrong or maybe what I have to change?
P.S.: "geluidknop" is Dutch for "soundbutton".
var audio = new Audio('Beep.mp3');
function playAudio() {
audio.play();
}
function pauseAudio() {
audio.pause();
audio.currentTime = 0;
}
window.addEventListener('keydown', playAudio);
audio.play();
function CanvasApp() {
'use strict'
var canvas = document.getElementById("canvas"),
style = window.getComputedStyle(canvas),
context = canvas.getContext("2d"),
source1 = "geluidaan.png",
source2 = "geluiduit.png",
click = false,
geluidknop = {x: 0, y: 0, width: 1024, height: 768};
geluidknop.aspect = geluidknop.height / geluidknop.width;
geluidknop.width = 500;
geluidknop.height = geluidknop.width * geluidknop.aspect;
canvas.width = parseInt(style.width, 10);
canvas.height = parseInt(style.height, 10);
var img = new Image();
img.onload = function () {
context.drawImage (img, geluidknop.x, geluidknop.y, geluidknop.width, geluidknop.height);
};
img.src = source1;
function changeImage() {
if (click) {
img.src = source2;
} else {
img.src = source1;
}
}
function MouseClick() {
var rect = canvas.getBoundingClientRect(),
x = event.clientX - rect.left,
y = event.clientY - rect.top;
if (x >= geluidknop.x && x <= geluidknop.x + geluidknop.width) {
if (y >= geluidknop.y && y <= geluidknop.y + geluidknop.height) {
if (click) {
click = false;
playAudio();
changeImage();
}else {
click = true;
pauseAudio();
changeImage();
}
}
}
context.save();
context.setTransform(1, 0, 0, 1, 0, 0);
context.clearRect(0, 0, canvas.width, canvas.height);
context.restore();
}
canvas.addEventListener('click', MouseClick);
function restartAudio() {
audio.currentTime = 0;
audio.play();
}
audio.addEventListener('ended', restartAudio);
}
function WindowLoaded() {
'use strict';
CanvasApp();
}
window.addEventListener("load", WindowLoaded);
I think you forgot to pass event to your event handler function. Chrome will fill this in, but Firefox will not.
It should be:
function MouseClick(event) {}
This issue might not be your code, but more likley .mp3 support in firefox.
Dependant on the version of firefox he was using a .mp3 file might not be supported
check out the mozilla docs on audio support

Generating new canvas dynamically in javascript

I have a canvas that I can draw things what I want to do is generate new canvases dynamically when clicking a button.I've defined a generate function but it did not work
here is script
//<![CDATA[
window.addEventListener('load', function () {
// get the canvas element and its context
var canvas = document.getElementById('sketchpad');
var context = canvas.getContext('2d');
// create a drawer which tracks touch movements
var drawer = {
isDrawing: false,
touchstart: function (coors) {
context.beginPath();
context.moveTo(coors.x, coors.y);
this.isDrawing = true;
},
touchmove: function (coors) {
if (this.isDrawing) {
context.lineTo(coors.x, coors.y);
context.stroke();
}
},
touchend: function (coors) {
if (this.isDrawing) {
this.touchmove(coors);
this.isDrawing = false;
}
}
};
// create a function to pass touch events and coordinates to drawer
function draw(event) {
var type = null;
// map mouse events to touch events
switch(event.type){
case "mousedown":
event.touches = [];
event.touches[0] = {
pageX: event.pageX,
pageY: event.pageY
};
type = "touchstart";
break;
case "mousemove":
event.touches = [];
event.touches[0] = {
pageX: event.pageX,
pageY: event.pageY
};
type = "touchmove";
break;
case "mouseup":
event.touches = [];
event.touches[0] = {
pageX: event.pageX,
pageY: event.pageY
};
type = "touchend";
break;
}
// touchend clear the touches[0], so we need to use changedTouches[0]
var coors;
if(event.type === "touchend") {
coors = {
x: event.changedTouches[0].pageX,
y: event.changedTouches[0].pageY
};
}
else {
// get the touch coordinates
coors = {
x: event.touches[0].pageX,
y: event.touches[0].pageY
};
}
type = type || event.type
// pass the coordinates to the appropriate handler
drawer[type](coors);
}
// detect touch capabilities
var touchAvailable = ('createTouch' in document) || ('ontouchstart' in window);
// attach the touchstart, touchmove, touchend event listeners.
if(touchAvailable){
canvas.addEventListener('touchstart', draw, false);
canvas.addEventListener('touchmove', draw, false);
canvas.addEventListener('touchend', draw, false);
}
// attach the mousedown, mousemove, mouseup event listeners.
else {
canvas.addEventListener('mousedown', draw, false);
canvas.addEventListener('mousemove', draw, false);
canvas.addEventListener('mouseup', draw, false);
}
// prevent elastic scrolling
document.body.addEventListener('touchmove', function (event) {
event.preventDefault();
}, false); // end body.onTouchMove
}, false); // end window.onLoad
function generate(){
var newCanvas = document.createElement('canvas');
newCanvas.width = 400;
newCanvas.height = 400;
document.getElementById('container').appendChild(newCanvas);
ctx = newCanvas.getContext('2d');
}
//]]>
here is jsfiddle http://jsfiddle.net/regeme/WVUwn/
ps:drawing not displayed on jsfiddle however it works on my localhost I have totally no idea about it , anyway what I need is generate function , I did but I think I am missing something..
Any ideas? thanks..
Below is a function I wrote to dynamically create canvas.
If the canvas already exists (same ID) then that canvas is returned.
The pixelRatio parameter can be defaulted to 1. It's used for setting the correct size on retina displays (so for iPhone with Retina the value would be 2)
function createLayer(sizeW, sizeH, pixelRatio, id, zIndex) {
// *** An id must be given.
if (typeof id === undefined) {
return false;
}
// *** If z-index is less than zero we'll make it a buffer image.
isBuffer = (zIndex < 0) ? true : false;
// *** If the canvas exist, clean it and just return that.
var element = document.getElementById(id);
if (element !== null) {
return element;
}
// *** If no zIndex is passed in then default to 0.
if (typeof zIndex === undefined || zIndex < 0) {
zIndex = 0;
}
var canvas = document.createElement('canvas');
canvas.width = sizeW;
canvas.height = sizeH;
canvas.id = id;
canvas.style.width = sizeW*pixelRatio + "px";
canvas.style.height = sizeH*pixelRatio + "px";
canvas.style.position = "absolute";
canvas.style.zIndex = zIndex;
if (!isBuffer) {
var body = document.getElementsByTagName("body")[0];
body.appendChild(canvas);
}
return canvas;
}
Change the jsfiddle option
"onLoad"
to
"No Wrap - in <body>"
EDIT: See also similar question over here: Uncaught ReferenceError for a function defined in an onload function
JSFiddle options: http://doc.jsfiddle.net/basic/introduction.html#frameworks-and-extensions
This is the working update of your JSFIDDLE
javascript:
document.getElementById('generate').addEventListener('mousedown', generate, false);
I guess this is what you want.
I've just added an eventListener to your button in javascript code itself.
P.S.: I've also added black background color to canvas to show it on white background.

Canvas and animation

I was trying to create a sample paint application using HTML 5 canvas. Then I added a button to redraw what user had drawn earlier. I am not sure what I am doing wrong or may be completely wrong. When I click redraw button multiple times it generates some magical animation by drawing lines all over. Even though if I log the starting point of drawing the image its same every time.
Demo: http://jsfiddle.net/BW57H/6/
Steps to reproduce:
Draw some circle or rectangle or something by clicking the mouse and dragging it on the rectangular box. Then click reset and redraw , click redraw couple of times after that and see the result.
I am not sure what I have done. I have not read a lot about Canvas. But I am curious to know what is going on here. Thanks.
html
<body>
<canvas id="paint" width="600px" height="300px"></canvas>
<div id="controls">
<button name="reset" id="reset">Reset</button>
<button name="redraw" id="redraw">Re-Draw</button>
</div>
</body>
css
#paint{
border: solid;
}
js
$(document).ready(function(){
var x, y, context, painter;
var xCounter = 0 , yCounter = 0;
var xarray = [];
var yarray = [];
function init(){
while(document.getElementById("paint") === undefined){
//do nothing
}
console.log("Loaded document now registering events for canvas");
var canvas = document.getElementById("paint");
context = canvas.getContext('2d');
painter = new Painter();
canvas.addEventListener('mousedown', capture, false);
canvas.addEventListener('mouseup', capture, false);
canvas.addEventListener('mousemove', capture, false);
document.getElementById("reset").addEventListener("click",function(){ clearCanvas(canvas);}, false);
document.getElementById("redraw").addEventListener("click", function(){
autoDraw();
}, false);
}
function clearCanvas(canvas){
context.save();
// Use the identity matrix while clearing the canvas
context.setTransform(1, 0, 0, 1, 0, 0);
context.clearRect(0, 0, canvas.width, canvas.height);
// Restore the transform
context.restore();
};
function capture(event){
if(event.which !== 1){
return;
}
x = event.layerX;
y = event.layerY;
switch(event.type){
case 'mousedown':
painter.startPaint(event);
break;
case 'mouseup':
painter.endPaint(event);
break;
case 'mousemove':
painter.paint(event);
break;
}
};
var Painter = function(){
var self = this;
self.paintStarted = false;
self.startPaint = function(event){
self.resetRecordingParams();
self.paintStarted = true;
context.beginPath();
context.moveTo(x,y);
self.record();
}
self.endPaint = function(event){
self.paintStarted = false;
self.record();
self.paint(event)
}
self.paint = function(event){
if(self.paintStarted){
context.lineTo(x,y);
context.stroke();
self.record();
}
}
self.record = function(){
xarray[xCounter++] = x;
yarray[yCounter++] = y;
}
self.resetRecordingParams = function(){
xarray = [];
yarray = [];
xCounter = 0;
yCounter= 0;
}
return self;
}
function autoDraw(){
context.beginPath();
console.log('starting at: '+xarray[0]+','+yarray[0]);
context.moveTo(xarray[0],yarray[0]);
for (var i = 0; i < xarray.length; i++) {
setTimeout(drawLineSlowly, 1000+(i*20), i);
};
}
function drawLineSlowly(i)
{
context.lineTo(xarray[i],yarray[i]);
context.stroke();
}
init();
});
You don't have any kind of check to see whether or not you are already drawing, so here is your code with those changes commented, as well as the real-pixel-location fixes (http://jsfiddle.net/upgradellc/htJXy/1/):
$(document).ready(function(){
var x, y, context, painter, canvas;
var xCounter = 0 , yCounter = 0;
var xarray = [];
var yarray = [];
function init(){
while(document.getElementById("paint") === undefined){
//do nothing
}
console.log("Loaded document now registering events for canvas");
canvas = document.getElementById("paint");
context = canvas.getContext('2d');
painter = new Painter();
canvas.addEventListener('mousedown', capture, false);
canvas.addEventListener('mouseup', capture, false);
canvas.addEventListener('mousemove', capture, false);
document.getElementById("reset").addEventListener("click",function(){ clearCanvas(canvas);}, false);
document.getElementById("redraw").addEventListener("click", function(){
autoDraw();
}, false);
}
function clearCanvas(canvas){
context.save();
// Use the identity matrix while clearing the canvas
context.setTransform(1, 0, 0, 1, 0, 0);
context.clearRect(0, 0, canvas.width, canvas.height);
// Restore the transform
context.restore();
};
function capture(event){
if(event.which !== 1){
return;
}
tempPos = getMousePos(canvas, event);
x = tempPos.x;
y = tempPos.y;
switch(event.type){
case 'mousedown':
painter.startPaint(event);
break;
case 'mouseup':
painter.endPaint(event);
break;
case 'mousemove':
painter.paint(event);
break;
}
};
var Painter = function(){
var self = this;
self.paintStarted = false;
//this keeps track of whether or not we are currently auto drawing
self.currentlyAutoDrawing = false;
self.startPaint = function(event){
self.resetRecordingParams();
self.paintStarted = true;
context.beginPath();
context.moveTo(x,y);
self.record();
}
self.endPaint = function(event){
self.paintStarted = false;
self.record();
self.paint(event);
}
self.paint = function(event){
if(self.paintStarted){
context.lineTo(x,y);
context.stroke();
self.record();
}
}
self.record = function(){
xarray[xCounter++] = x;
yarray[yCounter++] = y;
}
self.resetRecordingParams = function(){
xarray = [];
yarray = [];
xCounter = 0;
yCounter= 0;
}
return self;
}
function autoDraw(){
context.beginPath();
//If we are already auto-drawing, then we should just return instead of starting another drawing loop cycle
if(painter.currentlyAutoDrawing){
console.log("painter is already auto drawing");
return;
}
painter.currentlyAutoDrawing = true;
console.log('starting at: '+xarray[0]+','+yarray[0]);
context.moveTo(xarray[0],yarray[0]);
for (var i = 0; i < xarray.length; i++) {
setTimeout(drawLineSlowly, 1000+(i*20), i);
};
}
function drawLineSlowly(i)
{
//when we reach the last element in the array, update painter with the fact that autodrawing is now complete
if(xarray.length == i+1){
painter.currentlyAutoDrawing=false;
}
console.log(xarray.length+" "+i);
context.lineTo(xarray[i],yarray[i]);
context.stroke();
}
function getMousePos(canv, evt) {
var rect = canv.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
init();
});
Obviously you don't stop the previous timeout loop before you start a new...
Use setInterval instead of setTimeout, and clearInterval by next push. So I think the problem is not with the canvas, just with your redraw animation. Btw it is strange because there is some difference between the redraw and the original draw...
var drawInterval = null;
function autoDraw(){
if (drawInterval) {
//here your can reset the previous - still running - redraw
clearInterval(drawInterval);
}
context.beginPath();
console.log('starting at: '+xarray[0]+','+yarray[0]);
context.moveTo(xarray[0],yarray[0]);
var i=0;
setInterval(function (){
++i;
if (i<xarray.length)
drawLineSlowly(i);
else
clearInterval(drawInterval);
},20);
}
note:
There is still bug in the redraw, but at least it does not kill the browser...
Btw the strange "animation" is because you does not check by redraw if you are currently drawing or not, so you start draw and redraw together and they interfere... You have to stop redraw when you start drawing.

Categories