Dessiner sur HTML5 Canvas à l'aide d'une souris

110

Je souhaite dessiner sur un canevas HTML à l'aide d'une souris (ex: dessiner une signature, dessiner un nom, ...)

S'il vous plaît, aidez-moi comment puis-je faire? Veuillez donner du code source. Je vous remercie

MartinJoo
la source

Réponses:

224

Voici un exemple de travail.

 <html>
    <script type="text/javascript">
    var canvas, ctx, flag = false,
        prevX = 0,
        currX = 0,
        prevY = 0,
        currY = 0,
        dot_flag = false;

    var x = "black",
        y = 2;
    
    function init() {
        canvas = document.getElementById('can');
        ctx = canvas.getContext("2d");
        w = canvas.width;
        h = canvas.height;
    
        canvas.addEventListener("mousemove", function (e) {
            findxy('move', e)
        }, false);
        canvas.addEventListener("mousedown", function (e) {
            findxy('down', e)
        }, false);
        canvas.addEventListener("mouseup", function (e) {
            findxy('up', e)
        }, false);
        canvas.addEventListener("mouseout", function (e) {
            findxy('out', e)
        }, false);
    }
    
    function color(obj) {
        switch (obj.id) {
            case "green":
                x = "green";
                break;
            case "blue":
                x = "blue";
                break;
            case "red":
                x = "red";
                break;
            case "yellow":
                x = "yellow";
                break;
            case "orange":
                x = "orange";
                break;
            case "black":
                x = "black";
                break;
            case "white":
                x = "white";
                break;
        }
        if (x == "white") y = 14;
        else y = 2;
    
    }
    
    function draw() {
        ctx.beginPath();
        ctx.moveTo(prevX, prevY);
        ctx.lineTo(currX, currY);
        ctx.strokeStyle = x;
        ctx.lineWidth = y;
        ctx.stroke();
        ctx.closePath();
    }
    
    function erase() {
        var m = confirm("Want to clear");
        if (m) {
            ctx.clearRect(0, 0, w, h);
            document.getElementById("canvasimg").style.display = "none";
        }
    }
    
    function save() {
        document.getElementById("canvasimg").style.border = "2px solid";
        var dataURL = canvas.toDataURL();
        document.getElementById("canvasimg").src = dataURL;
        document.getElementById("canvasimg").style.display = "inline";
    }
    
    function findxy(res, e) {
        if (res == 'down') {
            prevX = currX;
            prevY = currY;
            currX = e.clientX - canvas.offsetLeft;
            currY = e.clientY - canvas.offsetTop;
    
            flag = true;
            dot_flag = true;
            if (dot_flag) {
                ctx.beginPath();
                ctx.fillStyle = x;
                ctx.fillRect(currX, currY, 2, 2);
                ctx.closePath();
                dot_flag = false;
            }
        }
        if (res == 'up' || res == "out") {
            flag = false;
        }
        if (res == 'move') {
            if (flag) {
                prevX = currX;
                prevY = currY;
                currX = e.clientX - canvas.offsetLeft;
                currY = e.clientY - canvas.offsetTop;
                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;" id="green" onclick="color(this)"></div>
        <div style="position:absolute;top:15%;left:46%;width:10px;height:10px;background:blue;" id="blue" onclick="color(this)"></div>
        <div style="position:absolute;top:15%;left:47%;width:10px;height:10px;background:red;" id="red" onclick="color(this)"></div>
        <div style="position:absolute;top:17%;left:45%;width:10px;height:10px;background:yellow;" id="yellow" onclick="color(this)"></div>
        <div style="position:absolute;top:17%;left:46%;width:10px;height:10px;background:orange;" id="orange" onclick="color(this)"></div>
        <div style="position:absolute;top:17%;left:47%;width:10px;height:10px;background:black;" id="black" onclick="color(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;" id="white" onclick="color(this)"></div>
        <img id="canvasimg" style="position:absolute;top:10%;left:52%;" style="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>

user1083202
la source
7
Pourquoi changez-vous? Vous pouvez également faire x = obj.id. Terminé.
MarijnS95
1
J'essaie d'utiliser ce code, mais j'ai des problèmes avec le dessin vertical lorsque je ne fais pas défiler complètement la page. Que dois-je changer dans ce code?
Cameron Darlington
8
J'ai changé canvas.offsetLeft;et canvas.offsetTop;avec canvas.getBoundingClientRect().left;et canvas.getBoundingClientRect().top;respectivement pour résoudre le problème de défilement.
KWILLIAMS
1
Ne fonctionne pas sur un écran tactile. Ne faisant pas référence aux comprimés. Je veux dire un ordinateur portable Windows 10 avec à la fois une souris et un écran tactile.
Paul
2
pour que cela fonctionne avec un stylo de dessin (comme une tablette graphique), les événements de souris doivent être remplacés par des événements tactiles, par exemple. touchmove, touchstart, touchendPuis le clientXvient de e.touches["0"].clientXdans le findxy()code, n'ont pas pensé à un moyen facile de détecter ce qui est utilisé si, comme vous ne pouvez pas écouter les deux événements en même temps de ce que je l' ai testé. Je suis parti mouseouttel quel. Ce n'est pas parfait, mais cela fonctionne
Jacob David C. Cunningham
38

Voici le moyen le plus simple de créer une application de dessin avec un canevas:

  1. Attachez un mousedown, mousemoveet mouseupécouteur d'événement sur la toile DOM
  2. activé mousedown, obtenez les coordonnées de la souris et utilisez la moveTo()méthode pour positionner votre curseur de dessin et la beginPath()méthode pour commencer un nouveau chemin de dessin.
  3. activé mousemove, ajoutez en continu un nouveau point au tracé avec lineTo()et coloriez le dernier segment avec stroke().
  4. activé mouseup, définissez un indicateur pour désactiver le dessin.

À partir de là, vous pouvez ajouter toutes sortes d'autres fonctionnalités, comme donner à l'utilisateur la possibilité de choisir une épaisseur de ligne, une couleur, des coups de pinceau et même des calques.

Eric Rowell
la source
28

Je pense que d'autres exemples ici sont trop compliqués. Celui-ci est plus simple et JS uniquement ...

// create canvas element and append it to document body
var canvas = document.createElement('canvas');
document.body.appendChild(canvas);

// some hotfixes... ( ≖_≖)
document.body.style.margin = 0;
canvas.style.position = 'fixed';

// get canvas 2D context and set him correct size
var ctx = canvas.getContext('2d');
resize();

// last known position
var pos = { x: 0, y: 0 };

window.addEventListener('resize', resize);
document.addEventListener('mousemove', draw);
document.addEventListener('mousedown', setPosition);
document.addEventListener('mouseenter', setPosition);

// new position from mouse event
function setPosition(e) {
  pos.x = e.clientX;
  pos.y = e.clientY;
}

// resize canvas
function resize() {
  ctx.canvas.width = window.innerWidth;
  ctx.canvas.height = window.innerHeight;
}

function draw(e) {
  // mouse left button must be pressed
  if (e.buttons !== 1) return;

  ctx.beginPath(); // begin

  ctx.lineWidth = 5;
  ctx.lineCap = 'round';
  ctx.strokeStyle = '#c0392b';

  ctx.moveTo(pos.x, pos.y); // from
  setPosition(e);
  ctx.lineTo(pos.x, pos.y); // to

  ctx.stroke(); // draw it!
}

Matěj Pokorný
la source
1
@ RyanCameron.Me vient de commenter la ligne if (e.buttons !== 1) return;;-).
Matěj Pokorný
1
@ RyanCameron.Me Je viens d'essayer les derniers Chrome, Firefox et Edge et tout fonctionne ... Quel navigateur utilisez-vous?
Matěj Pokorný
1
@ RyanCameron.Me C'est plus probablement parce que ma resizefonction. Je règle la largeur et la hauteur de la toile en fonction de la taille de la fenêtre. Vous devez les définir en fonction de votre <div class="container-fluid">.
Matěj Pokorný
1
cela a également aidé à soustraire environ 250 de la coordonnée y sur la fonction de position définie. Merci beaucoup pour votre aide!
RyanCameron.Me
1
@ TaylorA.Leach oui, si la toile n'est pas placée dans le coin supérieur droit, vous devrez en ajouter offsetdans la setPositionfonction ...
Matěj Pokorný
25

Googlé ceci ("programme de peinture de toile html5"). Ressemble à ce dont vous avez besoin.

http://dev.opera.com/articles/view/html5-canvas-painting/

Mike Robinson
la source
Cet exemple montre comment dessiner un cercle. Mais toujours le reste du bien. Une idée de la façon dont nous pouvons dessiner un cercle?
Ashwin
17

vérifiez ceci http://jsfiddle.net/ArtBIT/kneDX/ . Cela devrait vous orienter dans la bonne direction

Shadrack B. Orina
la source
1
parfait. devrait recevoir chk. J'avais besoin d'un moyen de créer de simples rectangles remplis sur une image existante. votre code est exactement ce dont j'avais besoin pour un modèle. tyvm!
11

Je cherchais également à utiliser cette méthode pour les signatures, j'ai trouvé un échantillon sur http://codetheory.in/ .

J'ai ajouté le code ci-dessous à un 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();
    };

}());
Sam Jones
la source
La meilleure partie est que vous pouvez dessiner des lignes droites connectées en cliquant avec le bouton droit de la souris à différents endroits. :)
Aidiakapi
Ne fonctionne pas sur un écran tactile. Ne faisant pas référence aux comprimés. Je veux dire un ordinateur portable Windows 10 avec à la fois une souris et un écran tactile.
Paul
5

Voici ma toile de travail très simple dessiner et effacer.

https://jsfiddle.net/richardcwc/d2gxjdva/

//Canvas
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
//Variables
var canvasx = $(canvas).offset().left;
var canvasy = $(canvas).offset().top;
var last_mousex = last_mousey = 0;
var mousex = mousey = 0;
var mousedown = false;
var tooltype = 'draw';

//Mousedown
$(canvas).on('mousedown', function(e) {
    last_mousex = mousex = parseInt(e.clientX-canvasx);
	last_mousey = mousey = parseInt(e.clientY-canvasy);
    mousedown = true;
});

//Mouseup
$(canvas).on('mouseup', function(e) {
    mousedown = false;
});

//Mousemove
$(canvas).on('mousemove', function(e) {
    mousex = parseInt(e.clientX-canvasx);
    mousey = parseInt(e.clientY-canvasy);
    if(mousedown) {
        ctx.beginPath();
        if(tooltype=='draw') {
            ctx.globalCompositeOperation = 'source-over';
            ctx.strokeStyle = 'black';
            ctx.lineWidth = 3;
        } else {
            ctx.globalCompositeOperation = 'destination-out';
            ctx.lineWidth = 10;
        }
        ctx.moveTo(last_mousex,last_mousey);
        ctx.lineTo(mousex,mousey);
        ctx.lineJoin = ctx.lineCap = 'round';
        ctx.stroke();
    }
    last_mousex = mousex;
    last_mousey = mousey;
    //Output
    $('#output').html('current: '+mousex+', '+mousey+'<br/>last: '+last_mousex+', '+last_mousey+'<br/>mousedown: '+mousedown);
});

//Use draw|erase
use_tool = function(tool) {
    tooltype = tool; //update
}
canvas {
    cursor: crosshair;
    border: 1px solid #000000;
}
<canvas id="canvas" width="800" height="500"></canvas>
<input type="button" value="draw" onclick="use_tool('draw');" />
<input type="button" value="erase" onclick="use_tool('erase');" />
<div id="output"></div>

Richard
la source
4

Alco vérifier celui-ci:
Exemple:
https://github.com/williammalone/Simple-HTML5-Drawing-App

Documentation:
http://www.williammalone.com/articles/create-html5-canvas-javascript-drawing-app/

Ce document comprend les codes suivants: -

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

Et un autre exemple génial
http://perfectionkills.com/exploring-canvas-drawing-techniques/

Vusan
la source
4

Je devais fournir un exemple simple pour ce sujet donc je vais partager ici:

http://jsfiddle.net/Haelle/v6tfp2e1

class SignTool {
  constructor() {
    this.initVars()
    this.initEvents()
  }

  initVars() {
    this.canvas = $('#canvas')[0]
    this.ctx = this.canvas.getContext("2d")
    this.isMouseClicked = false
    this.isMouseInCanvas = false
    this.prevX = 0
    this.currX = 0
    this.prevY = 0
    this.currY = 0
  }

  initEvents() {
    $('#canvas').on("mousemove", (e) => this.onMouseMove(e))
    $('#canvas').on("mousedown", (e) => this.onMouseDown(e))
    $('#canvas').on("mouseup", () => this.onMouseUp())
    $('#canvas').on("mouseout", () => this.onMouseOut())
    $('#canvas').on("mouseenter", (e) => this.onMouseEnter(e))
  }
  
  onMouseDown(e) {
  	this.isMouseClicked = true
    this.updateCurrentPosition(e)
  }
  
  onMouseUp() {
  	this.isMouseClicked = false
  }
  
  onMouseEnter(e) {
  	this.isMouseInCanvas = true
    this.updateCurrentPosition(e)
  }
  
  onMouseOut() {
  	this.isMouseInCanvas = false
  }

  onMouseMove(e) {
    if (this.isMouseClicked && this.isMouseInCanvas) {
    	this.updateCurrentPosition(e)
      this.draw()
    }
  }
  
  updateCurrentPosition(e) {
      this.prevX = this.currX
      this.prevY = this.currY
      this.currX = e.clientX - this.canvas.offsetLeft
      this.currY = e.clientY - this.canvas.offsetTop
  }
  
  draw() {
    this.ctx.beginPath()
    this.ctx.moveTo(this.prevX, this.prevY)
    this.ctx.lineTo(this.currX, this.currY)
    this.ctx.strokeStyle = "black"
    this.ctx.lineWidth = 2
    this.ctx.stroke()
    this.ctx.closePath()
  }
}

var canvas = new SignTool()
canvas {
  position: absolute;
  border: 2px solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" width="500" height="300"></canvas>

Haelle
la source
2

Cela fait des années que la question a été posée et a reçu une réponse.

Pour tous ceux qui recherchent un canevas de dessin simple (par exemple, pour prendre la signature de l'utilisateur / client), je publie ici une version jquery plus simplifiée de la réponse actuellement acceptée

$(document).ready(function() {
  var flag, dot_flag = false,
	prevX, prevY, currX, currY = 0,
	color = 'black', thickness = 2;
  var $canvas = $('#canvas');
  var ctx = $canvas[0].getContext('2d');

  $canvas.on('mousemove mousedown mouseup mouseout', function(e) {
    prevX = currX;
    prevY = currY;
    currX = e.clientX - $canvas.offset().left;
    currY = e.clientY - $canvas.offset().top;
    if (e.type == 'mousedown') {
      flag = true;
    }
    if (e.type == 'mouseup' || e.type == 'mouseout') {
      flag = false;
    }
    if (e.type == 'mousemove') {
      if (flag) {
        ctx.beginPath();
        ctx.moveTo(prevX, prevY);
        ctx.lineTo(currX, currY);
        ctx.strokeStyle = color;
        ctx.lineWidth = thickness;
        ctx.stroke();
        ctx.closePath();
      }
    }
  });

  $('.canvas-clear').on('click', function(e) {
    c_width = $canvas.width();
    c_height = $canvas.height();
    ctx.clearRect(0, 0, c_width, c_height);
    $('#canvasimg').hide();
  });
});
<html>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
  <body>
    <canvas id="canvas" width="400" height="400" style="position:absolute;top:10%;left:10%;border:2px solid;"></canvas>
    <input type="button" value="Clear" class="canvas-clear" />
  </body>
</html>

Munawir
la source
1

Faites-moi savoir si vous rencontrez des difficultés pour la mettre en œuvre. Il utilise processing.js et possède des fonctionnalités pour changer les couleurs et agrandir de plus en plus le point de dessin.

<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>
expiré
la source
Qu'est-ce que c'est init.js?
Majid Fouladpour
Je ne le comprends pas, mais le traitement commence.
expiré le
1

Une version super courte, ici , sans position:absoluteJavaScript vanille. L'idée principale est de déplacer le contexte du canevas vers les bonnes coordonnées et de tracer une ligne. Uncomment clickgestionnaire et commentaires mousedownet mousemovegestionnaires ci - dessous pour avoir une idée de la façon dont il fonctionne.

<!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>
Nitine
la source
Il est important de ne pas définir la largeur et la hauteur en CSS car cela ne fait qu'étirer le canevas au lieu de le redimensionner - stackoverflow.com/a/8693791/1585523
Nitin
0

si vous avez une image d'arrière-plan pour votre toile, vous devrez faire quelques ajustements pour qu'elle fonctionne correctement car une astuce d'effacement du blanc masquera l'arrière-plan.

voici l' essentiel du 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>
Mohammed Essehemy
la source