Drawing lines on dynamically added canvases - javascript

I am trying to set up a script to draw lines on dynamically added canvases, so there could be any number of canvases on the page. This is the script for the code so far, but it's not showing the lines or drawing when clicked on. I think the issue is in the drawLine function. The canvases will be added via a second script which also adds other elements.
<script type="text/javascript">
// Variables to keep track of the mouse position and left-button status
var mouseX,mouseY,mouseDown=0;
// Variables to keep track of the touch position
var touchX,touchY;
function drawLine(ctx,x,y,size) {
// If lastX is not set, set lastX and lastY to the current position
if (lastX==-1) {
lastX=x;
lastY=y;
}
// Let's use black by setting RGB values to 0, and 255 alpha (completely opaque)
r=0; g=0; b=0; a=255;
// Select a fill style
ctx.strokeStyle = "rgba("+r+","+g+","+b+","+(a/255)+")";
// Set the line "cap" style to round, so lines at different angles can join into each other
ctx.lineCap = "round";
//ctx.lineJoin = "round";
// Draw a filled line
ctx.beginPath();
// First, move to the old (previous) position
ctx.moveTo(lastX,lastY);
// Now draw a line to the current touch/pointer position
ctx.lineTo(x,y);
// Set the line thickness and draw the line
ctx.lineWidth = size;
ctx.stroke();
ctx.closePath();
// Update the last position to reference the current position
lastX=x;
lastY=y;
}
// Get the current mouse position relative to the top-left of the canvas
function getMousePos(e) {
if (!e)
var e = event;
if (e.offsetX) {
mouseX = e.offsetX;
mouseY = e.offsetY;
}
else if (e.layerX) {
mouseX = e.layerX;
mouseY = e.layerY;
}
}
// Get the touch position relative to the top-left of the canvas
// When we get the raw values of pageX and pageY below, they take into account the scrolling on the page
// but not the position relative to our target div. We'll adjust them using "target.offsetLeft" and
// "target.offsetTop" to get the correct values in relation to the top left of the canvas.
function getTouchPos(e) {
if (!e)
var e = event;
if(e.touches) {
if (e.touches.length == 1) { // Only deal with one finger
var touch = e.touches[0]; // Get the information for finger #1
touchX=touch.pageX-touch.target.offsetLeft;
touchY=touch.pageY-touch.target.offsetTop;
}
}
}
// Keep track of the mouse button being released
function sketchpad_mouseUp() {
mouseDown=0;
}
// Set-up an individual sketchpad and add our event handlers
// Use the "this" reference to make sure variables and functions are specific to each
// specific sketchpad created in the "init()" function below.
function sketchpad(my_sketchpad) {
// Get the specific canvas element from the HTML document passed
this.canvas = document.getElementById(my_sketchpad);
// If the browser supports the canvas tag, get the 2d drawing context for this canvas,
// and also store it with the canvas as "ctx" for convenience
if (this.canvas.getContext)
this.ctx = this.canvas.getContext('2d');
// Declare some functions associated with a particular sketchpad
// We will attach these to the canvas as event handlers later
// Note that the sketcphad_mouseUp function is not included here, since it's not
// specific to a certain canvas - we're listening to the entire window for mouseup
// events.
// Clear the canvas context using the canvas width and height
this.clearCanvas = function() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
// Draw something when a touch start is detected
this.sketchpad_touchStart = function() {
// Update the touch co-ordinates
getTouchPos();
drawLine(this.ctx,touchX,touchY,12);
// Prevents an additional mousedown event being triggered
event.preventDefault();
}
// Draw something and prevent the default scrolling when touch movement is detected
this.sketchpad_touchMove = function(e) {
// Update the touch co-ordinates
getTouchPos(e);
// During a touchmove event, unlike a mousemove event, we don't need to check if the touch is engaged, since there will always be contact with the screen by definition.
drawLine(this.ctx,touchX,touchY,12);
// Prevent a scrolling action as a result of this touchmove triggering.
event.preventDefault();
}
// Keep track of the mouse button being pressed and draw a dot at current location
this.sketchpad_mouseDown = function() {
mouseDown=1;
drawLine(this.ctx,mouseX,mouseY,12);
}
// Keep track of the mouse position and draw a dot if mouse button is currently pressed
this.sketchpad_mouseMove = function(e) {
// Update the mouse co-ordinates when moved
getMousePos(e);
// Draw a dot if the mouse button is currently being pressed
if (mouseDown==1) {
drawLine(this.ctx,mouseX,mouseY,12);
}
}
// Add event handlers
// Check that we have a valid context to draw on/with before adding event handlers
if (this.ctx) {
// React to mouse events on the canvas, and mouseup on the entire document
this.canvas.addEventListener('mousedown', this.sketchpad_mouseDown.bind(this), false);
this.canvas.addEventListener('mousemove', this.sketchpad_mouseMove.bind(this), false);
// React to touch events on the canvas
this.canvas.addEventListener('touchstart', this.sketchpad_touchStart.bind(this), false);
this.canvas.addEventListener('touchmove', this.sketchpad_touchMove.bind(this), false);
}
}
// Create two sketchpads when the page loads, using our canvas elements called sketchpad1 and sketchpad2
function init() {
sketch1 = new sketchpad('sketchpad1');
//sketch2 = new sketchpad('sketchpad2');
// Since we are listening to the entire window for the mouseup, it only needs to be done once per page,
// and not once per canvas
window.addEventListener('mouseup', sketchpad_mouseUp, false);
}

Your troubles have nothing to do with the how the canvases are added.
var touchX,touchY;
Should be:
var touchX,touchY,lastX=-1,lastY=-1;

Related

Receiving the coordinates of a mouse drag

I want to get coordinates of a mouse drag.
I have canvas and inside him I draw same object after I want to get the coordinates of the new mouse (pixel) grab the object,
my code is in javascript.
my object not in tag elemnts of html just drawing inside the canvas with pixel and I want to grab him with mouse and need the new coordination of the mouse.
Thanks,
Canvas is a kind of 2d image element/tag, so there is no direct way to drag the objects inside canvas.
You need to listen for mouse events inside the canvas, and repaint the canvas based on these events.
Listen these 3 events for dragging the objects inside canvas
function handleMouseDown(e) {
var mousePos = getMousePosition(canvas, e);
// if current position matches the object postion
// set a flag and monitor mouse move and mouse up event
}
function handleMouseUp(e) {
var mousePos = getMousePosition(canvas, e);
//if your flag is true, then move the object to here and reset flag
}
function handleMouseMove(e) {
var mousePos = getMousePosition(canvas, e);
//Handle if you need smooth drag experience
}
function getMousePosition(canvas, e) {
var boundary = canvas.getBoundingClientRect();
// (e.clientX, e.clientY) => Mouse coordinates wrt whole browser
// (boundary.left, boundary.top) => Canvas starting coordinate
return {
x: e.clientX - boundary.left,
y: e.clientY - boundary.top
};
}
var canvas = document.getElementById('canvasId');
canvas.addEventListener('mousemove', handleMouseMove, false);
canvas.addEventListener('mousedown', handleMouseDown, false);
canvas.addEventListener('mouseup', handleMouseUp, false);

Do DOM events work with pointer lock?

I have used the pointer lock on my canvas element, and the canvas is on full screen. I want to detect right clicks and left clicks to respond to them. Is it possible to respond to clicks in full screen and pointer lock? I already know how to use the pointer lock api and the fullscreen api, I don't want any answers explaining how to use them. Any help would be appreciated.
Based on the experiments I've done, the short answer is "it depends." Take a look at the following demo. There is a canvas scaled to be a quarter of the screen size in each dimension. When you move the cursor over it, a white circle appears on the canvas. When you left click, you'll draw a red circle to the canvas, and when you right click, you'll draw a cyan circle to the canvas. When you click the "Full screen" button, you'll activate pointer lock and enter fullscreen mode. If you press the "Esc" key, you'll exit pointer lock and fullscreen mode.
Note that you'll need to copy and paste the code into a file and load it. The demo won't run if you just click "Run code snippet."
As far as your question, there are two issues, I'm aware of:
In Chrome, both right- and left-click events are triggered even while in fullscreen/pointer lock. However, in Firefox, only left-click events are triggered; I was unable to get right-click events using any of the handlers I tried (click, mousedown, mouseup, contextmenu). When not in fullscreen/pointer lock, both left- and right-click events get triggered as expected in both browsers. If anyone has any solutions for listening to right-click events while in fullscreen/pointer lock, I'd love to hear them.
It seems that in pointer lock in both Chrome/Firefox, events no longer trickle down to elements contained in the element with pointer lock, but they continue to bubble up to parent elements. So in the demo, the canvas is inside a div. The div has pointer lock. onclick handlers are attached to the canvas, div, and document to report click events in the console. Without pointer lock, clicking on the canvas triggers onclick handlers for all three elements (canvas, div, and document). However, with pointer lock on the div, the onclick handler for the canvas never gets triggered, though the handlers for the div and the document do.
I also identified a couple other quirks to Firefox that, while not directly related to your initial question, might be helpful to folks interested in implementing this sort of thing:
When fullscreen mode is entered, Firefox will apply styles to the fullscreen element to get it to fill the screen. I was unable to get the canvas styled correctly (i.e. to take up the full screen) when it was placed full screen. Rather, I had to wrap the canvas in a div and enter full screen on the div. See the Fullscreen API documentation on MDN for more info:
if you're trying to emulate WebKit's behavior on Gecko, you need to place the element you want to present inside another element, which you'll make fullscreen instead, and use CSS rules to adjust the inner element to match the appearance you want.
In Firefox, activating fullscreen mode deactivated pointer lock. In order to get both activated, I had to first activate fullscreen mode and then activate pointer lock. However the simple two lines of code:
canvasContainer.requestFullscreen();
canvasContainer.requestPointerLock();
did not work. My understanding of what was happening is that the call to requestPointerLock got initiated before full screen mode was fully established. This led to pointer lock being activated and then quickly deactivated again. I found it necessary to wait until fullscreen mode was fully established before calling requestPointerLock(). Checking that document.mozFullScreenElement !== null seemed to be sufficient for checking that full screen mode was completely operational. The following following click handler definition worked to solve this problem for me:
document.getElementById('fullscreen_button').onclick = function(e) {
// When button is clicked, enter both full screen and pointer lock
canvasContainer.requestFullscreen();
var timeout = 2000;
var interval = window.setInterval(function() {
if (document.mozFullScreenElement !== null) {
window.clearInterval(interval);
canvasContainer.requestPointerLock();
} else if (timeout <= 0) {
addErrorMessage('Unable to establish pointer lock.');
clearTimeout(interval);
} else {
timeout -= 50;
}
}, 50);
}
This function repeatedly checks if full screen mode is established. When it is, it initiate pointer lock. If fullscreen mode can't be determined after 2 s, it times out.
I haven't done any testing in IE.
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<style>
</style>
</head>
<body>
<p id="msgs">Click 'Full screen' button below to go full screen. <br>
Click the left mouse button to draw a red circle. <br>
Click any other mouse button to draw a cyan circle. <br>
Press the 'Esc' key to exit full screen.</p>
<div id="canvas_container">
<canvas id="canvas"> </canvas>
</div>
<br>
<button id='fullscreen_button'>Full screen</button>
</body>
<script>
// Display constants
var CANVAS_BG_COLOR = 'rgb(75, 75, 75)';
var LEFT_CLICK_COLOR = 'rgb(255, 150, 150)';
var OTHER_CLICK_COLOR = 'rgb(150, 255, 255)';
var CURSOR_COLOR = 'rgb(200, 200, 200)';
var CANVAS_SCALING_FACTOR = 4; // Ratio between screen dimension and canvas dimension before going full-screen
// Store mouse position
var mouseX, mouseY;
// Setup onscreen canvas, smaller than the screen by a factor of CANVAS_SCALING_FACTOR
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = screen.width/CANVAS_SCALING_FACTOR;
canvas.height = screen.height/CANVAS_SCALING_FACTOR;
// Create an offscreen canvas that's the same as the size of the screen
var offscreenCanvas = document.createElement('canvas');
var offscreenCtx = offscreenCanvas.getContext('2d');
offscreenCanvas.width = screen.width;
offscreenCanvas.height = screen.height;
var canvasContainer = document.getElementById('canvas_container');
// Radius of the circle drawn and of the circle cursor
var circleRadius = 12;
var cursorRadius = circleRadius/CANVAS_SCALING_FACTOR
offscreenCtx.drawCircle = ctx.drawCircle = function (x, y, color, radius) {
this.fillStyle = color;
this.beginPath();
this.arc(x, y, radius, 0, 2*Math.PI, true);
this.fill();
}
offscreenCtx.clearCanvas = function() {
this.fillStyle = CANVAS_BG_COLOR;
this.fillRect(0, 0, this.canvas.width, this.canvas.height);
}
ctx.update = function() {
// Copy the offscreen canvas, scaling down if not in full-screen mode
this.drawImage(offscreenCanvas, 0, 0, offscreenCanvas.width, offscreenCanvas.height,
0, 0, canvas.width, canvas.height);
// Draw the cursor
this.drawCircle(mouseX, mouseY, CURSOR_COLOR, cursorRadius);
}
function pointerLockActive() {
return document.pointerLockElement===canvasContainer || document.mozPointerLockElement === canvasContainer;
}
// Perform initial canvas setup
offscreenCtx.clearCanvas();
ctx.update();
// Setup pointerlock and fullscreen API functions for cross-browser support
function addErrorMessage(msg) {
document.getElementById('msgs').innerHTML += ('<br><font color="red">' + msg + '</font>');
}
canvasContainer.requestPointerLock = canvasContainer.requestPointerLock || canvasContainer.mozRequestPointerLock;
canvasContainer.requestFullscreen = canvasContainer.webkitRequestFullscreen || canvasContainer.mozRequestFullScreen || canvasContainer.msRequestFullscreen
if (!canvasContainer.requestPointerLock) addErrorMessage('Error: Pointer lock not available');
if (!canvasContainer.requestFullscreen) addErrorMessage('Error: Full screen mode not available');
canvasContainer.addEventListener('mousemove', function(e) {
if (pointerLockActive()) {
// If in pointer lock, then cursor positions need to be updated manually;
// Normal cursor positions (e.g. e.clientX and e.clientY) don't get updated in pointer lock
mouseX += e.movementX, mouseY += e.movementY;
// Prevent the mouse from moving off-screen
mouseX = Math.min(Math.max(0, mouseX), canvas.width);
mouseY = Math.min(Math.max(0, mouseY), canvas.height);
} else {
// If pointer lock is inactive, then mouse position is just position relative to canvas offset
mouseX = (e.pageX - canvas.offsetLeft)
mouseY = (e.pageY - canvas.offsetTop)
}
ctx.update(); // Update the onscreen canvas
}, false);
// Handle entering and exiting pointer lock; pointer lock status is yoked to full screen status; both are entered and exited at the same time
document.addEventListener('pointerlockchange', function(e) {
if (!pointerLockActive()) {
console.log('Pointer lock deactivated');
canvas.width /= CANVAS_SCALING_FACTOR;
canvas.height /= CANVAS_SCALING_FACTOR
cursorRadius /= CANVAS_SCALING_FACTOR;
} else {
console.log('Pointer lock activated')
canvas.width *= CANVAS_SCALING_FACTOR;
canvas.height *= CANVAS_SCALING_FACTOR;
cursorRadius *= CANVAS_SCALING_FACTOR;
// Set the initial mouse position to be the middle of the canvas
mouseX = screen.width/2, mouseY = screen.height/2;
}
// Update the onscreen canvas
ctx.update();
});
document.getElementById('fullscreen_button').onclick = function(e) {
// When button is clicked, enter both full screen and pointer lock
canvasContainer.requestFullscreen();
var timeout = 2000;
var interval = window.setInterval(function() {
if (document.mozFullScreenElement !== null) {
window.clearInterval(interval);
canvasContainer.requestPointerLock();
} else if (timeout <= 0) {
addErrorMessage('Unable to establish pointer lock.');
clearTimeout(interval);
} else {
timeout -= 50;
}
}, 50);
}
canvasContainer.onclick = function(e) {
console.log('canvasContainer clicked');
if (pointerLockActive())
// If pointer lock is active, then use the mouseX and mouseY positions that are manually updated by the mousemove event handler
var cursorX = mouseX, cursorY = mouseY;
else
// Otherwise use the mouse positions passed in the event object
// If not in full screen mode, the cursor position has to be scaled up, because the mouse position is relative to the onscreen canvas, but we're drawing on the offscreen canvas, which is larger by a factor of fullscreenScale
var cursorX = (e.pageX - canvas.offsetLeft)*CANVAS_SCALING_FACTOR, cursorY = (e.pageY - canvas.offsetTop)*CANVAS_SCALING_FACTOR;
// If the left mouse button is clicked (e.which===1), draw a circle of one color
// If any other mouse button is clicked, draw a circle of another color
var color = e.which === 1 ? LEFT_CLICK_COLOR : OTHER_CLICK_COLOR;
offscreenCtx.drawCircle(cursorX, cursorY, color, circleRadius);
ctx.update();
};
// Detect canvas right-click events. Prevent default behavior (e.g. context menu display) and pass on to the onclick handler to do the rest of the work
canvasContainer.oncontextmenu = function(e) {
e.preventDefault();
this.onclick(e);
}
canvas.onclick = function() {
console.log('canvas clicked');
}
document.onclick = function() {
console.log('document clicked');
}
</script>
</html>
This worked for me to handle rightClick after pointer was locked.
const onMouseDown = (evt) => {
switch (evt.which) {
case 1: return handleLeftClick();
case 3: return handleRightClick();
}
};
document.body.addEventListener('mousedown', onMouseDown, true);

html5 canvas drawing: fast motion with mouse cancels line before it hits the edge of the canvas

The app works fine so far except if the line is drawn really fast and leaves the edge of the canvas, the line is then not drawn to the edge of the canvas. There is a part missing from it.
I'm trying to fix the issue with:
canvasVar.addEventListener ('mouseout', clearPathIfMouseCursorLeavesCanvasFunc);
and
function clearPathIfMouseCursorLeavesCanvasFunc(e){
contextVar.beginPath(); // clears the path so buttonpresses dont connect the line
mouseButtonHeld = false;
I've tried some things like adding a settimeout(); but nothing worked so far. I don't know what causes this and I've been searching if someone else had this problem and a fix for it, but every canvas drawing app I've come across has the same issues.
It's very important that the line is drawn to the edge and that the users mouse motion is recognized, not just a line to the last coordinates where the mouse left the canvas.
It's been days now that I'm stuck with this problem. Help is really appreciated!
Whole Code:
// Varibale declaration
var canvasVar = document.getElementById('canvasHtmlElement');
var contextVar = canvasVar.getContext('2d');
var pointRadiusVar = 0.5;
var mouseButtonHeld = false;
var pointsArrPosition = 0;
//Arrays
var pointsArr = [];
// Varibale declration end
//canvas setup
canvasVar.width = window.innerWidth;
canvasVar.height = window.innerHeight;
//canvas setup end
//resize fix
window.onresize = function() {
var tempImageVar = contextVar.getImageData(0, 0, canvasVar.width, canvasVar.height);
canvasVar.width = window.innerWidth;
canvasVar.height = window.innerHeight;
contextVar.putImageData(tempImageVar, 0, 0);
}
//resize fix end
//functions
// Objects
function pointObject() {
this.x = 0;
this.y = 0;
this.fill = '#444444';
}
function addFilledCircleFunc(x, y) {
//alert('works1');
var filledCircle = new pointObject;
filledCircle.x = x;
filledCircle.y = y;
pointsArr.push(filledCircle);
contextVar.lineWidth = 10; //pointRadiusVar * 2; // Line Width
contextVar.lineTo(pointsArr[pointsArrPosition].x, pointsArr[pointsArrPosition].y);
contextVar.stroke();
//contextVar.beginPath();
contextVar.fillRect(filledCircle.x, filledCircle.y, 1, 1);
//contextVar.arc(filledCircle.x, filledCircle.y, pointRadiusVar, 0, Math.PI * 2);
//contextVar.fill();
//contextVar.lineWidth = 0.5;
//contextVar.stroke();
//contextVar.beginPath();
pointsArrPosition++;
//contextVar.moveTo(pointsArr[pointsArrPosition].x, pointsArr[pointsArrPosition].y);
//alert(pointsArr[0].x);
}
//Objects end
// create circle on mouse clicked point while mousebutton is held
var addPointToCanvasVar = function(e) {
if (mouseButtonHeld) {
//alert('addpointfunc');
addFilledCircleFunc(e.clientX, e.clientY);
}
};
// MAKE SURE that lines work when drawn over the edge of the canvas
function clearPathIfMouseCursorLeavesCanvasFunc(e) {
contextVar.beginPath(); // clears the path so buttonpresses dont connect the line
mouseButtonHeld = false;
}
// end
// mouse Up/Down functions
var mouseDownVar = function(e) {
//alert("mouseDown");
addPointToCanvasVar(e); // add point on first click, not just when mousebutton is held
mouseButtonHeld = true;
}
var mouseUpVar = function() {
//alert("mouseUp");
mouseButtonHeld = false;
contextVar.beginPath(); // clears the path so buttonpresses dont connect the line
}
// mouse Up/Down Switch end
//functions end
//listeners
canvasVar.addEventListener('mousemove', addPointToCanvasVar);
canvasVar.addEventListener('mouseup', mouseUpVar);
canvasVar.addEventListener('mousedown', mouseDownVar);
canvasVar.addEventListener('mouseout', clearPathIfMouseCursorLeavesCanvasFunc);
//listeners end
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Confident Drawing</title>
</head>
<body style="margin: 0">
<canvas id="canvasHtmlElement" style="display: block;">
Your Browser does not support Canvas! Please update to a newer version.
</canvas>
<script src="main_0.06.js"></script>
</body>
</html>
If you don't get what I mean: Run the snippet and draw a line as fast as you can while exiting the canvas.
The reason the line ends prematurely near the edge when you quickly draw a line across the edge is because the last mousemove event fired when the mouse was still in the canvas and just short of the edge, and the very next mousemove event fired after your mouse left the canvas. To fix that problem, simply draw your line from the last recorded mouse position in the canvas to the one outside of the canvas as soon as the mouseout event fires.
You can add a new global variable mousePosition and initialize it to {x:0,y:0}. Every time mousemove fires (whenever you call addPointToCanvasVar), record the e.clientX and e.clientY to your mousePosition. Then when mouseout fires (whenever you call clearPathIfMouseCursorLeavesCanvasFunc), draw the rest of the line from mousePosition to the current e.clientX and e.clientY position. This will complete the line to the end of the canvas edge.

Touch-screen <canvas> for signatures not working on touch-screen devices

The canvas signing works with mouse but isn't working with mobile. What am I missing?
When I use the canvas on my computer, the mouse-draw feature works well but when I open the file via mobile, the signature pad doesn't work. I have looked through my code but I can't identify the problem. Any ideas?
The HTML:
<!--The Signature Pad & Clear Button-->
<canvas id="sketchpad" width="500" height="200" style="background-color:#C4C4C4"></canvas>
<button type="button" value="Clear Sketchpad" id="clearbutton" onclick="clearCanvas(canvas,ctx);">Clear</button>
The JavaScript:
<script type="text/javascript">
// Variables for referencing the canvas and 2dcanvas context
var canvas,ctx;
// Variables to keep track of the mouse position and left-button status
var mouseX,mouseY,mouseDown=0;
// Variables to keep track of the touch position
var touchX,touchY;
// Draws a dot at a specific position on the supplied canvas name
// Parameters are: A canvas context, the x position, the y position, the size of the dot
function drawDot(ctx,x,y,size) {
// Let's use black by setting RGB values to 0, and 255 alpha (completely opaque)
r=0; g=0; b=0; a=255;
// Select a fill style
ctx.fillStyle = "rgba("+r+","+g+","+b+","+(a/255)+")";
// Draw a filled circle
ctx.beginPath();
ctx.arc(x, y, size, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
}
// Clear the canvas context using the canvas width and height
function clearCanvas(canvas,ctx) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
// Keep track of the mouse button being pressed and draw a dot at current location
function sketchpad_mouseDown() {
mouseDown=1;
drawDot(ctx,mouseX,mouseY,4);
}
// Keep track of the mouse button being released
function sketchpad_mouseUp() {
mouseDown=0;
}
// Kepp track of the mouse position and draw a dot if mouse button is currently pressed
function sketchpad_mouseMove(e) {
// Update the mouse co-ordinates when moved
getMousePos(e);
// Draw a dot if the mouse button is currently being pressed
if (mouseDown==1) {
drawDot(ctx,mouseX,mouseY,4);
}
}
// Get the current mouse position relative to the top-left of the canvas
function getMousePos(e) {
if (!e)
var e = event;
if (e.offsetX) {
mouseX = e.offsetX;
mouseY = e.offsetY;
}
else if (e.layerX) {
mouseX = e.layerX;
mouseY = e.layerY;
}
}
// Draw something when a touch start is detected
function sketchpad_touchStart() {
// Update the touch co-ordinates
getTouchPos();
drawDot(ctx,touchX,touchY,4);
// Prevents an additional mousedown event being triggered
event.preventDefault();
}
// Draw something and prevent the default scrolling when touch movement is detected
function sketchpad_touchMove(e) {
// Update the touch co-ordinates
getTouchPos(e);
// During a touchmove event, unlike a mousemove event, we don't need to check if the touch is engaged, since there will always be contact with the screen by definition.
drawDot(ctx,touchX,touchY,4);
// Prevent a scrolling action as a result of this touchmove triggering.
event.preventDefault();
}
// Get the touch position relative to the top-left of the canvas
// When we get the raw values of pageX and pageY below, they take into account the scrolling on the page
// but not the position relative to our target div. We'll adjust them using "target.offsetLeft" and
// "target.offsetTop" to get the correct values in relation to the top left of the canvas.
function getTouchPos(e) {
if (!e)
var e = event;
if(e.touches) {
if (e.touches.length == 1) { // Only deal with one finger
var touch = e.touches[0]; // Get the information for finger #1
touchX=touch.pageX-touch.target.offsetLeft;
touchY=touch.pageY-touch.target.offsetTop;
}
}
}
// Set-up the canvas and add our event handlers after the page has loaded
function init() {
// Get the specific canvas element from the HTML document
canvas = document.getElementById('sketchpad');
// If the browser supports the canvas tag, get the 2d drawing context for this canvas
if (canvas.getContext)
ctx = canvas.getContext('2d');
// Check that we have a valid context to draw on/with before adding event handlers
if (ctx) {
// React to mouse events on the canvas, and mouseup on the entire document
canvas.addEventListener('mousedown', sketchpad_mouseDown, false);
canvas.addEventListener('mousemove', sketchpad_mouseMove, false);
window.addEventListener('mouseup', sketchpad_mouseUp, false);
// React to touch events on the canvas
canvas.addEventListener('touchstart', sketchpad_touchStart, false);
canvas.addEventListener('touchmove', sketchpad_touchMove, false);
}
}
</script>
I have fixed this buy removing the "position:relative;" from the parent div of canvas.

Canvas Drawing Application Wont Work in Firefox

I'm working on this little drawing application type thing, but it won't work in Firefox. It works fine in chrome though. Here's the javascript, then I just have a regular old canvas element in HTML. Any help is appreciated!
/* FOR THE DRAWING APPLICATION */
/* =========================== */
var canvasMouse, contextMouse;
var started = false;
var x, y;
function initMouse() {
// Get the drawing canvas
canvasMouse = document.getElementById('drawing');
contextMouse = canvasMouse.getContext('2d');
// Add some event listeners so we can figure out what's happening
// and run a few functions when they are executed.
canvasMouse.addEventListener('mousemove', mousemovement, false);
canvasMouse.addEventListener('mousedown', mouseclick, false);
canvasMouse.addEventListener('mouseup', mouseunclick, false);
}
function mouseclick() {
// When the mouse is clicked. Change started to true and move
// the initial position to the position of the mouse
contextMouse.beginPath();
contextMouse.moveTo(x, y);
started = true;
}
function mousemovement(e) {
// Get moust position
x = e.offsetX;
y = e.offsetY;
// If started is true, then draw a line
if(started) {
contextMouse.lineTo(x, y);
contextMouse.stroke();
}
}
function mouseunclick() {
// Change started to false when the user unclicks the mouse
if(started) {
started = false;
}
}
Any ideas?
offsetX and offsetY are not supported in firefox (see compatibility table here). Instead you need to use layerX and layerY.
The following will work in firefox (see fiddle):
/* FOR THE DRAWING APPLICATION */
/* =========================== */
var canvasMouse, contextMouse;
var started = false;
var x, y;
function initMouse() {
// Get the drawing canvas
canvasMouse = document.getElementById('drawing');
contextMouse = canvasMouse.getContext('2d');
// Add some event listeners so we can figure out what's happening
// and run a few functions when they are executed.
canvasMouse.addEventListener('mousemove', mousemovement, false);
canvasMouse.addEventListener('mousedown', mouseclick, false);
canvasMouse.addEventListener('mouseup', mouseunclick, false);
}
function mouseclick(e) {
// When the mouse is clicked. Change started to true and move
// the initial position to the position of the mouse
// Get moust position
x = e.layerX;
y = e.layerY;
console.log("coords", x, y);
contextMouse.beginPath();
contextMouse.moveTo(x, y);
started = true;
}
function mousemovement(e) {
// Get mouset position
x = e.layerX;
y = e.layerY;
console.log("coords", x, y);
// If started is true, then draw a line
if(started) {
contextMouse.lineTo(x, y);
contextMouse.stroke();
}
}
function mouseunclick() {
// Change started to false when the user unclicks the mouse
if(started) {
started = false;
}
}
initMouse();
If you want to avoid browser specific conditional code and / or your canvas element is offset within the DOM hierarchy (read the limitations of layerX and layerY in the compatibility table linked to above), there may be an argument for using jQuery and its position() method.

Categories