How to draw outside of an HTML canvas element? - javascript

I have an HTML canvas element and have implemented a brush that captures the mousedown, mousemove, and mouseup events of the canvas element. This all works fine for drawing on the canvas. However, I don't think I like how you can't continue a drawing if your mouse leaves the canvas mid stroke. It kind of just cuts it off. It's very unforgiving to the person and not very user-friendly in my opinion.
If you open up Microsoft Paint and begin drawing with the brush or ellipse or something, as long as you start within the canvas, you can drag your mouse anywhere on your screen and re-enter the canvas wherever. It also makes it easy, for example, to draw quarter-circles in corners because you can drag the ellipse tool off-screen. I hope this makes sense.
Anyways, I was wondering if there was a way to implement this with the HTML5 canvas or how I would go about implementing this sort of thing. The user would never have to actually seen anything drawn over there; it's mostly just going to be a feature for usability.
Edit: A problem with a lot of these solutions is how to handle coordinates. Currently my canvas is in the middle of the screen and the top left of the canvas is (0, 0) and the bottom right is (500, 500). The translation work of the coordinates has to be considered as well.
Edit2: I found out that apparently you can draw off the canvas bounds just fine. For example, you can supply negative widths, heights, and coordinates and the canvas element will handle it just fine. So basically the solution will likely involve just capturing the document's mousemove and mouseup and just translating the x and y to start at the canvas's top left corner.

Here is one way you can keep drawing when reenter the canvas:
Create a global variable and set that one to true on mousedown
Add a global event for mouseup so you can catch if someone do that outside
the canvas, and if so, set global variable to false, and the canvas element's mouseup need of course also to set the same variable
On mousemove, check for global variable to be true before draw
To draw "outside" the canvas, like quarter-circles in a corner, I would move all events to the document level as global handler and catch the canvas element on click and pass its client coordinates to be computed with the document coordinates.

Here is an extremely rough first draft of how you can listen for mouse events on the window rather than the canvas to be able to draw continuously:
var logger = document.getElementById("logger"),
mState = document.getElementById("mState"),
mX = document.getElementById("mX"),
mY = document.getElementById("mY"),
cX = document.getElementById("cX"),
cY = document.getElementById("cY"),
c = document.getElementById("canvas"),
ctx = c.getContext("2d");
var mouse = {
x: 0,
y: 0,
state: ""
};
function printCanvasLocation() {
var b = c.getBoundingClientRect();
cX.innerHTML = b.top;
cY.innerHTML = b.left;
}
function setState(mouseE, state) {
mouse.x = mouseE.clientX;
mouse.y = mouseE.clientY;
mX.innerHTML = mouseE.clientX;
mY.innerHTML = mouseE.clientY;
if (state) {
mState.innerHTML = state;
mouse.state = state;
}
}
window.addEventListener("mousedown", function(mouseE) {
setState(mouseE, "down");
});
window.addEventListener("mouseup", function(mouseE) {
setState(mouseE, "up");
});
window.addEventListener("mousemove", function(mouseE) {
var offset = c.getBoundingClientRect();
var fix = {
x1: (mouse.x - offset.left),
y1: (mouse.y - offset.top),
x2: (mouseE.clientX - offset.left),
y2: (mouseE.clientY - offset.top)
};
if (mouse.state === "down") {
ctx.moveTo(fix.x1, fix.y1);
ctx.lineTo(fix.x2, fix.y2);
ctx.strokeStyle = "#000";
ctx.stroke();
}
setState(mouseE);
});
window.addEventListener("resize", function() {
printCanvasLocation();
});
printCanvasLocation();
.center {
text-align: center;
}
canvas {
background-color: lightblue;
}
<main>
<div class="center">
<canvas id="canvas" width="128" height="128">If you can see me, you should update your browser</canvas>
</div>
<div id="logger" role="log">
<span>State: </span><span id="mState">Unknown</span>
<span>X: </span><span id="mX">Unknown</span>
<span>Y: </span><span id="mY">Unknown</span>
<span>Canvas X: </span><span id="cX">Unknown</span>
<span>Canvas Y: </span><span id="cY">Unknown</span>
</div>
</main>

One solution would be to literally make the canvas the size of the window, and scale its size with it. The canvas can be mostly transparent.
I'm sure there's also a way to make mouse events and such go through the canvas first but then pass through to the elements behind, if that's desired. (See: "js events bubbling and capturing".)
But then you would have absolute control and be able to draw anything anywhere.

Related

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);

how to retain positions for images in fabric js

I am trying to work on image processing with fabric js.I am dealing with very huge images hence I have to save copy of canvases after image processing so that next time it can be shown faster with jquery's id.show. But I want to render the images on the exact location. I am using canvas.zoomToPoint and canvas.relativePan to zoom and pan the image but after I do zoom + pan and then apply image processing to show hidden canvas and apply hiddencanvas.zoomToPoint and hiddencanvas.relativePan on hidden canvas, it doesn't render the image on the exact location where I left the older canvas. Am I doing any mistake. Here's a supporting Fiddle .However, the fiddle renders a image by uploading and if you zoom and pan and click on invert, the inverted image doesn't move there Panning code : ` ``var panning = false;
canvas.on('mouse:up', function (e) {
panning = false;
});
canvas.on('mouse:down', function (e) {
panning = true;
});
canvas.on('mouse:move', function(e) {
if (panning && e && e.e) {
var x = e.offsetX, y = e.offsetY;
var delta = new fabric.Point(e.e.movementX, e.e.movementY);
canvas.relativePan(delta);
//Above statement pan's the image but what to save to server in order to render the image on the exact panned location ?
}
});
`` whereas this is zoom code : canvas.zoomToPoint({ x: x, y: y }, newZoom);
I found the answer , it was a very silly mistake .
Every canvas has a Viewport transform .
So, we just need to get canvas.viewportTransform and then we can get the ScaleX, scaleY, left , top as [scaleX, 0,0, scaleY, left,top] .
Hope , it will help someone .

Custom cursors for canvas caricatures?

I'm making a whiteboard app just for fun and have tools like the brush tool, eraser, etc and I draw on an HTML5 canvas.
I'm trying to implement custom cursors for my tools (like brush, line, square) and was just going to use the CSS cursor property depending on which tool is selected but I'd like sizes to vary depending on the current line width.
For example, in MS Paint you'll notice with the brush and eraser tool, depending on the size of the line width, the cursor is differently sized when drawing on the canvas.
So I have two questions. The first is if I can use CSS still and somehow alternate the cursor size dynamically from JS.
The second is how you would implement this solution by just deleting the cursor and drawing your own on the canvas that follows the mouse movement. I'm a bit concerned that the latter would be quite glitchy and more complex so am hoping that the first one is possible.
Maintaining the position of your own cursor does not work very well on the browsers. By the time you have handled the mouse move, waited for the next animation frame you are one frame behind. (drawing immediately to canvas in the mouse event does help) The is very off putting, even if you set the cursor to "none" so the two do not overlap, the 1/60th of a second can make a big difference from where you see your rendered cursor to and where the hardware cursor (for want of a better name) is.
But it turns out that the browsers Chrome and Firefox allow you to have full control of the hardware cursor image. I have personally exploited it to the limits and it is a robust and tolerant system.
I started with pre made cursors as DataURLs. But now most of my cursors are dynamic. If a control uses the mouse wheel, I add the wheel indicator on the cursor, when using resize cursor, instead of 8 directions N, NE, E, SE, S, SW, W, NW It is created on demand to line up with whatever I happen to be resizing at what ever angle it is. When drawing the cursor is continuously reorienting to avoid covering pixels I may be working on.
To set a custom cursor, set the elements style.cursor to an image URL, followed by two numbers that are the hotspot (Where the click is focused), and a cursor name. I just use the same name "pointer" and generate the image URL on the fly with toDataURL.
Below is a quick example of changing the cursor dynamically. I am unsure what the limits are in terms of size, but so far I haven't wanted a cursor that it has not given me. Some of them, in games have been very big (lol as cursors go) (128*128 pixels +)
Note a slight bug in code. Will return to fix the first rendered word being clipped soon.
The only issue with this is IE does not support this what of doing cursors, so you will need a fallback
// create an image to use to create cursors
var image = document.createElement("canvas");
image.width = 200;
image.height = 14;
image.ctx = image.getContext("2d");
// some graphic cursors
var cursors = [
"url('data:image/png;base64,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') 0 0, cursor",
"url('data:image/png;base64,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') 0 0, cursor ",
"url('data:image/png;base64,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') 0 0, cursor "
];
// Do the stuff that does the stuff
var el = document.getElementById("customeCurs");
var over = false;
// set up canvas rendering
var c = image.ctx;
// some stuff to say and ABC are graphic flags
var stuff = "A C Hello pointy clicky things are great and easy to use A B C B".split(" ");
var tHandle;
var wordPos=0;
function createCursor(){ // creates cursors from the canvas
// get a word from the word list
var w = stuff[wordPos % stuff.length];
if(w === "A" || w === "B" || w === "C"){ // display graphics cursor
// just for fun. to much time on
// my hands. I really need a job.
var datURL;
switch(w){
case "A":
datURL = cursors[0];
break;
case "B":
datURL = cursors[1];
break;
case "C":
datURL = cursors[2];
}
el.style.cursor = datURL;
}else{ // create a dynamic cursor from canvas image
// get the size. Must do this
var size = c.measureText(w).width + 4;
// resize the canvas
image.width = size;
image.height = 36;
c.font = "28px arial black";
c.textAlign ="center";
c.textBaseline = "middle";
c.lineCap = "round";
c.lineJoin = "round";
// Please always give user a visual guide to the hotspot.
// following draws a little arrow to the hotspot.
// Always outline as single colours can get lost to the background
c.lineWidth = 3;
c.strokeStyle = "white";
c.moveTo(1,5);
c.lineTo(1,1);
c.lineTo(5,1);
c.moveTo(1,1);
c.lineTo(8,8);
c.stroke();
c.strokeStyle = "black";
c.lineWidth = 1;
c.moveTo(1,5);
c.lineTo(1,1);
c.lineTo(5,1);
c.moveTo(1,1);
c.lineTo(8,8);
c.stroke();
c.lineWidth = 5;
c.strokeStyle = "black";
c.fillStyle = "White";
// Draw the text outline
c.strokeText(w, image.width / 2, image.height / 2+2);
// and inside
c.fillText(w, image.width / 2, image.height / 2);
// create a cursor and add it to the element CSS curso property
el.style.cursor = "url('"+image.toDataURL("image/png")+"') 0 0 , pointer"; // last two
// numbers are the
// cursor hot spot.
}
// Next word
wordPos += 1;
// if the mouse still over then do it again in 700 ticks of the tocker.
if(over){
tHandle = setTimeout(createCursor,700);
}
}
// mouse over event to start cursor rendering
el.addEventListener("mouseover",function(){
over = true;
if(tHandle === undefined){
createCursor();
}
});
el.addEventListener("mouseout",function(){
over = false; // clean up if the mouse moves out. But leave the cursor
clearTimeout(tHandle);
tHandle = undefined;
});
<div id="customeCurs" >Move Mouse Over ME.</div>
<!-- Some say don't put style in HTML doc! The standards are indifferent. The author is lazy :P -->
<span style="font-size:small;color:#BBB;">Sorry IE again you miss out.</span>

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.

Categories