I want to draw on a HTML Canvas using a mouse (for example, draw a signature, draw a name, ...)
How would I go about implementing this?
This question is related to
html
canvas
gesture
gesture-recognition
Here is my very simple working canvas draw and erase.
https://jsfiddle.net/richardcwc/d2gxjdva/
//Canvas_x000D_
var canvas = document.getElementById('canvas');_x000D_
var ctx = canvas.getContext('2d');_x000D_
//Variables_x000D_
var canvasx = $(canvas).offset().left;_x000D_
var canvasy = $(canvas).offset().top;_x000D_
var last_mousex = last_mousey = 0;_x000D_
var mousex = mousey = 0;_x000D_
var mousedown = false;_x000D_
var tooltype = 'draw';_x000D_
_x000D_
//Mousedown_x000D_
$(canvas).on('mousedown', function(e) {_x000D_
last_mousex = mousex = parseInt(e.clientX-canvasx);_x000D_
last_mousey = mousey = parseInt(e.clientY-canvasy);_x000D_
mousedown = true;_x000D_
});_x000D_
_x000D_
//Mouseup_x000D_
$(canvas).on('mouseup', function(e) {_x000D_
mousedown = false;_x000D_
});_x000D_
_x000D_
//Mousemove_x000D_
$(canvas).on('mousemove', function(e) {_x000D_
mousex = parseInt(e.clientX-canvasx);_x000D_
mousey = parseInt(e.clientY-canvasy);_x000D_
if(mousedown) {_x000D_
ctx.beginPath();_x000D_
if(tooltype=='draw') {_x000D_
ctx.globalCompositeOperation = 'source-over';_x000D_
ctx.strokeStyle = 'black';_x000D_
ctx.lineWidth = 3;_x000D_
} else {_x000D_
ctx.globalCompositeOperation = 'destination-out';_x000D_
ctx.lineWidth = 10;_x000D_
}_x000D_
ctx.moveTo(last_mousex,last_mousey);_x000D_
ctx.lineTo(mousex,mousey);_x000D_
ctx.lineJoin = ctx.lineCap = 'round';_x000D_
ctx.stroke();_x000D_
}_x000D_
last_mousex = mousex;_x000D_
last_mousey = mousey;_x000D_
//Output_x000D_
$('#output').html('current: '+mousex+', '+mousey+'<br/>last: '+last_mousex+', '+last_mousey+'<br/>mousedown: '+mousedown);_x000D_
});_x000D_
_x000D_
//Use draw|erase_x000D_
use_tool = function(tool) {_x000D_
tooltype = tool; //update_x000D_
}
_x000D_
canvas {_x000D_
cursor: crosshair;_x000D_
border: 1px solid #000000;_x000D_
}
_x000D_
<canvas id="canvas" width="800" height="500"></canvas>_x000D_
<input type="button" value="draw" onclick="use_tool('draw');" />_x000D_
<input type="button" value="erase" onclick="use_tool('erase');" />_x000D_
<div id="output"></div>
_x000D_
if you have background image for your canvas, you will have to make some tweaks to have it work properly because white erasing trick will hide the background.
here is a gist with the code.
<html>
<script type="text/javascript">
var canvas, canvasimg, backgroundImage, finalImg;
var mouseClicked = false;
var prevX = 0;
var currX = 0;
var prevY = 0;
var currY = 0;
var fillStyle = "black";
var globalCompositeOperation = "source-over";
var lineWidth = 2;
function init() {
var imageSrc = '/abstract-geometric-pattern_23-2147508597.jpg'
backgroundImage = new Image();
backgroundImage.src = imageSrc;
canvas = document.getElementById('can');
finalImg = document.getElementById('finalImg');
canvasimg = document.getElementById('canvasimg');
canvas.style.backgroundImage = "url('" + imageSrc + "')";
canvas.addEventListener("mousemove", handleMouseEvent);
canvas.addEventListener("mousedown", handleMouseEvent);
canvas.addEventListener("mouseup", handleMouseEvent);
canvas.addEventListener("mouseout", handleMouseEvent);
}
function getColor(btn) {
globalCompositeOperation = 'source-over';
lineWidth = 2;
switch (btn.getAttribute('data-color')) {
case "green":
fillStyle = "green";
break;
case "blue":
fillStyle = "blue";
break;
case "red":
fillStyle = "red";
break;
case "yellow":
fillStyle = "yellow";
break;
case "orange":
fillStyle = "orange";
break;
case "black":
fillStyle = "black";
break;
case "eraser":
globalCompositeOperation = 'destination-out';
fillStyle = "rgba(0,0,0,1)";
lineWidth = 14;
break;
}
}
function draw(dot) {
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.globalCompositeOperation = globalCompositeOperation;
if(dot){
ctx.fillStyle = fillStyle;
ctx.fillRect(currX, currY, 2, 2);
} else {
ctx.beginPath();
ctx.moveTo(prevX, prevY);
ctx.lineTo(currX, currY);
ctx.strokeStyle = fillStyle;
ctx.lineWidth = lineWidth;
ctx.stroke();
}
ctx.closePath();
}
function erase() {
if (confirm("Want to clear")) {
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
document.getElementById("canvasimg").style.display = "none";
}
}
function save() {
canvas.style.border = "2px solid";
canvasimg.width = canvas.width;
canvasimg.height = canvas.height;
var ctx2 = canvasimg.getContext("2d");
// comment next line to save the draw only
ctx2.drawImage(backgroundImage, 0, 0);
ctx2.drawImage(canvas, 0, 0);
finalImg.src = canvasimg.toDataURL();
finalImg.style.display = "inline";
}
function handleMouseEvent(e) {
if (e.type === 'mousedown') {
prevX = currX;
prevY = currY;
currX = e.offsetX;
currY = e.offsetY;
mouseClicked = true;
draw(true);
}
if (e.type === 'mouseup' || e.type === "mouseout") {
mouseClicked = false;
}
if (e.type === 'mousemove') {
if (mouseClicked) {
prevX = currX;
prevY = currY;
currX = e.offsetX;
currY = e.offsetY;
draw();
}
}
}
</script>
<body onload="init()">
<canvas id="can" width="400" height="400" style="position:absolute;top:10%;left:10%;border:2px solid;">
</canvas>
<div style="position:absolute;top:12%;left:43%;">Choose Color</div>
<div style="position:absolute;top:15%;left:45%;width:10px;height:10px;background:green;" data-color="green" onclick="getColor(this)"></div>
<div style="position:absolute;top:15%;left:46%;width:10px;height:10px;background:blue;" data-color="blue" onclick="getColor(this)"></div>
<div style="position:absolute;top:15%;left:47%;width:10px;height:10px;background:red;" data-color="red" onclick="getColor(this)"></div>
<div style="position:absolute;top:17%;left:45%;width:10px;height:10px;background:yellow;" data-color="yellow" onclick="getColor(this)"></div>
<div style="position:absolute;top:17%;left:46%;width:10px;height:10px;background:orange;" data-color="orange" onclick="getColor(this)"></div>
<div style="position:absolute;top:17%;left:47%;width:10px;height:10px;background:black;" data-color="black" onclick="getColor(this)"></div>
<div style="position:absolute;top:20%;left:43%;">Eraser</div>
<div style="position:absolute;top:22%;left:45%;width:15px;height:15px;background:white;border:2px solid;" data-color="eraser" onclick="getColor(this)"></div>
<canvas id="canvasimg" style="display:none;" ></canvas>
<img id="finalImg" style="position:absolute;top:10%;left:52%;display:none;" >
<input type="button" value="save" id="btn" size="30" onclick="save()" style="position:absolute;top:55%;left:10%;">
<input type="button" value="clear" id="clr" size="23" onclick="erase()" style="position:absolute;top:55%;left:15%;">
</body>
</html>
I think, other examples here are too complicated. This one is simpler and JS only...
// create canvas element and append it to document body_x000D_
var canvas = document.createElement('canvas');_x000D_
document.body.appendChild(canvas);_x000D_
_x000D_
// some hotfixes... ( ?_?)_x000D_
document.body.style.margin = 0;_x000D_
canvas.style.position = 'fixed';_x000D_
_x000D_
// get canvas 2D context and set him correct size_x000D_
var ctx = canvas.getContext('2d');_x000D_
resize();_x000D_
_x000D_
// last known position_x000D_
var pos = { x: 0, y: 0 };_x000D_
_x000D_
window.addEventListener('resize', resize);_x000D_
document.addEventListener('mousemove', draw);_x000D_
document.addEventListener('mousedown', setPosition);_x000D_
document.addEventListener('mouseenter', setPosition);_x000D_
_x000D_
// new position from mouse event_x000D_
function setPosition(e) {_x000D_
pos.x = e.clientX;_x000D_
pos.y = e.clientY;_x000D_
}_x000D_
_x000D_
// resize canvas_x000D_
function resize() {_x000D_
ctx.canvas.width = window.innerWidth;_x000D_
ctx.canvas.height = window.innerHeight;_x000D_
}_x000D_
_x000D_
function draw(e) {_x000D_
// mouse left button must be pressed_x000D_
if (e.buttons !== 1) return;_x000D_
_x000D_
ctx.beginPath(); // begin_x000D_
_x000D_
ctx.lineWidth = 5;_x000D_
ctx.lineCap = 'round';_x000D_
ctx.strokeStyle = '#c0392b';_x000D_
_x000D_
ctx.moveTo(pos.x, pos.y); // from_x000D_
setPosition(e);_x000D_
ctx.lineTo(pos.x, pos.y); // to_x000D_
_x000D_
ctx.stroke(); // draw it!_x000D_
}
_x000D_
Googled this ("html5 canvas paint program"). Looks like what you need.
It's been years since the question was asked and was answered.
For anyone who looks for a simple drawing canvas (eg, for taking the signature from the user/customer), here I am posting a more simplified jquery version of the currently accepted answer
$(document).ready(function() {_x000D_
var flag, dot_flag = false,_x000D_
prevX, prevY, currX, currY = 0,_x000D_
color = 'black', thickness = 2;_x000D_
var $canvas = $('#canvas');_x000D_
var ctx = $canvas[0].getContext('2d');_x000D_
_x000D_
$canvas.on('mousemove mousedown mouseup mouseout', function(e) {_x000D_
prevX = currX;_x000D_
prevY = currY;_x000D_
currX = e.clientX - $canvas.offset().left;_x000D_
currY = e.clientY - $canvas.offset().top;_x000D_
if (e.type == 'mousedown') {_x000D_
flag = true;_x000D_
}_x000D_
if (e.type == 'mouseup' || e.type == 'mouseout') {_x000D_
flag = false;_x000D_
}_x000D_
if (e.type == 'mousemove') {_x000D_
if (flag) {_x000D_
ctx.beginPath();_x000D_
ctx.moveTo(prevX, prevY);_x000D_
ctx.lineTo(currX, currY);_x000D_
ctx.strokeStyle = color;_x000D_
ctx.lineWidth = thickness;_x000D_
ctx.stroke();_x000D_
ctx.closePath();_x000D_
}_x000D_
}_x000D_
});_x000D_
_x000D_
$('.canvas-clear').on('click', function(e) {_x000D_
c_width = $canvas.width();_x000D_
c_height = $canvas.height();_x000D_
ctx.clearRect(0, 0, c_width, c_height);_x000D_
$('#canvasimg').hide();_x000D_
});_x000D_
});
_x000D_
<html>_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>_x000D_
<body>_x000D_
<canvas id="canvas" width="400" height="400" style="position:absolute;top:10%;left:10%;border:2px solid;"></canvas>_x000D_
<input type="button" value="Clear" class="canvas-clear" />_x000D_
</body>_x000D_
</html>
_x000D_
check this http://jsfiddle.net/ArtBIT/kneDX/. This should direct you on the right direction
Here's the most straightforward way to create a drawing application with canvas:
mousedown
, mousemove
, and mouseup
event listener to the canvas DOMmousedown
, get the mouse coordinates, and use the moveTo()
method to position your drawing cursor and the beginPath()
method to begin a new drawing path.mousemove
, continuously add a new point to the path with lineTo()
, and color the last segment with stroke()
.mouseup
, set a flag to disable the drawing.From there, you can add all kinds of other features like giving the user the ability to choose a line thickness, color, brush strokes, and even layers.
I was looking to use this method for signatures as well, i found a sample on http://codetheory.in/.
I've added the below code to a jsfiddle
Html:
<div id="sketch">
<canvas id="paint"></canvas>
</div>
Javascript:
(function() {
var canvas = document.querySelector('#paint');
var ctx = canvas.getContext('2d');
var sketch = document.querySelector('#sketch');
var sketch_style = getComputedStyle(sketch);
canvas.width = parseInt(sketch_style.getPropertyValue('width'));
canvas.height = parseInt(sketch_style.getPropertyValue('height'));
var mouse = {x: 0, y: 0};
var last_mouse = {x: 0, y: 0};
/* Mouse Capturing Work */
canvas.addEventListener('mousemove', function(e) {
last_mouse.x = mouse.x;
last_mouse.y = mouse.y;
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
}, false);
/* Drawing on Paint App */
ctx.lineWidth = 5;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = 'blue';
canvas.addEventListener('mousedown', function(e) {
canvas.addEventListener('mousemove', onPaint, false);
}, false);
canvas.addEventListener('mouseup', function() {
canvas.removeEventListener('mousemove', onPaint, false);
}, false);
var onPaint = function() {
ctx.beginPath();
ctx.moveTo(last_mouse.x, last_mouse.y);
ctx.lineTo(mouse.x, mouse.y);
ctx.closePath();
ctx.stroke();
};
}());
A super short version, here, without position:absolute
in vanilla JavaScript. The main idea is to move the canvas' context to the right coordinates and draw a line. Uncomment click
handler and comment mousedown
& mousemove
handlers below to get a feel for how it is working.
<!DOCTYPE html>
<html>
<body>
<p style="margin: 50px">Just some padding in y direction</p>
<canvas id="myCanvas" width="300" height="300" style="background: #000; margin-left: 100px;">Your browser does not support the HTML5 canvas tag.</canvas>
<script>
const c = document.getElementById("myCanvas");
// c.addEventListener("click", penTool); // fires after mouse left btn is released
c.addEventListener("mousedown", setLastCoords); // fires before mouse left btn is released
c.addEventListener("mousemove", freeForm);
const ctx = c.getContext("2d");
function setLastCoords(e) {
const {x, y} = c.getBoundingClientRect();
lastX = e.clientX - x;
lastY = e.clientY - y;
}
function freeForm(e) {
if (e.buttons !== 1) return; // left button is not pushed yet
penTool(e);
}
function penTool(e) {
const {x, y} = c.getBoundingClientRect();
const newX = e.clientX - x;
const newY = e.clientY - y;
ctx.beginPath();
ctx.lineWidth = 5;
ctx.moveTo(lastX, lastY);
ctx.lineTo(newX, newY);
ctx.strokeStyle = 'white';
ctx.stroke();
ctx.closePath();
lastX = newX;
lastY = newY;
}
let lastX = 0;
let lastY = 0;
</script>
</body>
</html>
Alco check this one:
Example:
https://github.com/williammalone/Simple-HTML5-Drawing-App
Documentation:
http://www.williammalone.com/articles/create-html5-canvas-javascript-drawing-app/
This document includes following codes:-
HTML:
<canvas id="canvas" width="490" height="220"></canvas>
JS:
context = document.getElementById('canvas').getContext("2d");
$('#canvas').mousedown(function(e){
var mouseX = e.pageX - this.offsetLeft;
var mouseY = e.pageY - this.offsetTop;
paint = true;
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);
redraw();
});
$('#canvas').mouseup(function(e){
paint = false;
});
$('#canvas').mouseleave(function(e){
paint = false;
});
var clickX = new Array();
var clickY = new Array();
var clickDrag = new Array();
var paint;
function addClick(x, y, dragging)
{
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
}
//Also redraw
function redraw(){
context.clearRect(0, 0, context.canvas.width, context.canvas.height); // Clears the canvas
context.strokeStyle = "#df4b26";
context.lineJoin = "round";
context.lineWidth = 5;
for(var i=0; i < clickX.length; i++) {
context.beginPath();
if(clickDrag[i] && i){
context.moveTo(clickX[i-1], clickY[i-1]);
}else{
context.moveTo(clickX[i]-1, clickY[i]);
}
context.lineTo(clickX[i], clickY[i]);
context.closePath();
context.stroke();
}
}
And another awesome example
http://perfectionkills.com/exploring-canvas-drawing-techniques/
Let me know if you have trouble implementing this. It uses processing.js and has features for changing colors and making the draw point larger and smaller.
<html>
<head>
<!--script librarires-->
<script type="text/javascript" src="processing.js"></script>
<script type="text/javascript" src="init.js"></script>
<!--styles -->
<style type="text/css" src="stylesheet.css">
</style>
</head>
<body>
<!--toolbox -->
<div id="draggable toolbox"></div>
<script type="application/processing">
// new script
int prevx, prevy;
int newx, newy;
boolean cliked;
color c1 = #000000;
int largeur=2;
int ps = 20;
int px = 50;
int py = 50;
void setup() {
size(500,500);
frameRate(25);
background(50);
prevx = mouseX;
prevy = mouseY;
cliked = false;
}
void draw() {
//couleur
noStroke(0);
fill(#FFFFFF);//blanc
rect(px, py, ps, ps);
fill(#000000);
rect(px, py+(ps), ps, ps);
fill(#FF0000);
rect(px, py+(ps*2), ps, ps);
fill(#00FF00);
rect(px, py+(ps*3), ps, ps);
fill(#FFFF00);
rect(px, py+(ps*4), ps, ps);
fill(#0000FF);
rect(px, py+(ps*5), ps, ps);
//largeur
fill(#FFFFFF);
rect(px, py+(ps*7), ps, ps);
fill(#FFFFFF);
rect(px, py+(ps*8), ps, ps);
stroke(#000000);
line(px+2, py+(ps*7)+(ps/2), px+(ps-2), py+(ps*7)+(ps/2));
line(px+(ps/2), py+(ps*7)+1, px+(ps/2), py+(ps*8)-1);
line(px+2, py+(ps*8)+(ps/2), px+(ps-2), py+(ps*8)+(ps/2));
if(cliked==false){
prevx = mouseX;
prevy = mouseY;
}
if(mousePressed) {
cliked = true;
newx = mouseX;
newy = mouseY;
strokeWeight(largeur);
stroke(c1);
line(prevx, prevy, newx, newy);
prevx = newx;
prevy = newy;
}else{
cliked= false;
}
}
void mouseClicked() {
if (mouseX>=px && mouseX<=(px+ps)){
//couleur
if (mouseY>=py && mouseY<=py+(ps*6)){
c1 = get(mouseX, mouseY);
}
//largeur
if (mouseY>=py+(ps*7) && mouseY<=py+(ps*8)){
largeur += 2;
}
if (mouseY>=py+(ps*8) && mouseY<=py+(ps*9)){
if (largeur>2){
largeur -= 2;
}
}
}
}
</script><canvas></canvas>
</body>
</html>
I had to provide a simple example for this subject so I'll share here:
http://jsfiddle.net/Haelle/v6tfp2e1
class SignTool {_x000D_
constructor() {_x000D_
this.initVars()_x000D_
this.initEvents()_x000D_
}_x000D_
_x000D_
initVars() {_x000D_
this.canvas = $('#canvas')[0]_x000D_
this.ctx = this.canvas.getContext("2d")_x000D_
this.isMouseClicked = false_x000D_
this.isMouseInCanvas = false_x000D_
this.prevX = 0_x000D_
this.currX = 0_x000D_
this.prevY = 0_x000D_
this.currY = 0_x000D_
}_x000D_
_x000D_
initEvents() {_x000D_
$('#canvas').on("mousemove", (e) => this.onMouseMove(e))_x000D_
$('#canvas').on("mousedown", (e) => this.onMouseDown(e))_x000D_
$('#canvas').on("mouseup", () => this.onMouseUp())_x000D_
$('#canvas').on("mouseout", () => this.onMouseOut())_x000D_
$('#canvas').on("mouseenter", (e) => this.onMouseEnter(e))_x000D_
}_x000D_
_x000D_
onMouseDown(e) {_x000D_
this.isMouseClicked = true_x000D_
this.updateCurrentPosition(e)_x000D_
}_x000D_
_x000D_
onMouseUp() {_x000D_
this.isMouseClicked = false_x000D_
}_x000D_
_x000D_
onMouseEnter(e) {_x000D_
this.isMouseInCanvas = true_x000D_
this.updateCurrentPosition(e)_x000D_
}_x000D_
_x000D_
onMouseOut() {_x000D_
this.isMouseInCanvas = false_x000D_
}_x000D_
_x000D_
onMouseMove(e) {_x000D_
if (this.isMouseClicked && this.isMouseInCanvas) {_x000D_
this.updateCurrentPosition(e)_x000D_
this.draw()_x000D_
}_x000D_
}_x000D_
_x000D_
updateCurrentPosition(e) {_x000D_
this.prevX = this.currX_x000D_
this.prevY = this.currY_x000D_
this.currX = e.clientX - this.canvas.offsetLeft_x000D_
this.currY = e.clientY - this.canvas.offsetTop_x000D_
}_x000D_
_x000D_
draw() {_x000D_
this.ctx.beginPath()_x000D_
this.ctx.moveTo(this.prevX, this.prevY)_x000D_
this.ctx.lineTo(this.currX, this.currY)_x000D_
this.ctx.strokeStyle = "black"_x000D_
this.ctx.lineWidth = 2_x000D_
this.ctx.stroke()_x000D_
this.ctx.closePath()_x000D_
}_x000D_
}_x000D_
_x000D_
var canvas = new SignTool()
_x000D_
canvas {_x000D_
position: absolute;_x000D_
border: 2px solid;_x000D_
}
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<canvas id="canvas" width="500" height="300"></canvas>
_x000D_
Source: Stackoverflow.com