Comment puis-je dessiner à la main sur toile avec JavaScript?

Question

Comment puis-je dessiner librement (à l'aide de ma souris / de mes doigts) sur un élément de toile comme vous pouvez le faire en peinture avec un crayon?

A propos de cette question

il y a beaucoup de questions qui veulent réaliser le dessin main libre sur toile:

  • tirage au sort par la souris avec HTML5 Canvas
  • KineticJS - Dessiner avec la souris
  • dessin libre sur toile utilisant tissu.js
  • Croquis avec JS
  • Peinture toile ne fonctionne pas correctement
  • position de la Souris sur toile
  • mise en oeuvre d'une esquisse et d'un dessin lisses sur l'élément

alors j'ai pensé que ce serait une bonne idée de faire une question de référence, où chaque réponse est wiki communautaire et contient une explication pour exactement une bibliothèque JavaScript / JavaScript comment faire de la peinture sur toile.

Structure des réponses

les réponses doivent être le wiki de la communauté et utiliser le modèle suivant:

## [Name of library](Link to project page)
### Simple example
    A basic, complete example. That means it has to contain HTML 
    and JavaScript. You can start with this:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Simple example</title>
        <script type='text/javascript' src='http://cdnjs.com/[your library]'></script>
        <style type='text/css'>
            #sheet {
                border:1px solid black;
            }
        </style>
        <script type='text/javascript'>
            window.onload=function(){
                // TODO: Adjust
            }
        </script>
      </head>
      <body>
        <canvas id="sheet" width="400" height="400"></canvas>
      </body>
    </html>

    If possible, this example should work with both, mouse and touch events.

[JSFiddle](Link to code on jsfiddle.net)

This solution works with:

<!-- Please test it the following way: Write "Hello World"
  Problems that you test this way are:
   * Does it work at all?
   * Are lines separated?
   * Does it get slow when you write too much?
-->

* Desktop computers:
  * [Browser + Version list]
* Touch devices:
  * [Browser + Version list] on [Device name]

### Import / Export
Some explanations how to import / export user drawn images.

### Line smoothing
Explanations about how to manipulate the line the user draws. 
This can include:
  * Bézier curves
  * Controlling thickness of lines
19
demandé sur Community 2014-04-06 12:47:49

6 réponses

Tissu.js

<!DOCTYPE html>
<html>
  <head>
    <title>Simple example</title>
    <script type='text/javascript' src='http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.4.0/fabric.min.js'></script>
    <style type='text/css'>
        #sheet {
            border:1px solid black;
        }
    </style>
    <script type='text/javascript'>
        window.onload=function(){
            var canvas = new fabric.Canvas('sheet');
            canvas.isDrawingMode = true;
            canvas.freeDrawingBrush.width = 5;
            canvas.freeDrawingBrush.color = "#ff0000";
        }
    </script>
  </head>
  <body>
    <canvas id="sheet" width="400" height="400"></canvas>
  </body>
</html>

JSFiddle -Démo

  • la largeur des lignes peut être contrôlée avec canvas.freeDrawingBrush.width.
  • La couleur des lignes peut être contrôlé avec canvas.freeDrawingBrush.color.

Cette solution fonctionne avec:

  • ordinateurs de Bureau:
    • Chrome 33
    • Firefox 28
  • Touch appareil:
    • Chrome 34 sur Nexus 4
    • Opéra de 20 sur le Nexus 4
    • Firefox 28 sur le Nexus 4

Importer / Exporter

N'est possible qu'en sérialisant la toile complète, voir Tutoriel

lissage de la ligne

Se fait automatiquement et il ne semble pas possible de le désactiver.

8
répondu Martin Thoma 2016-08-07 23:04:29

JavaScript Simple

exemple Simple

<!DOCTYPE html>
<html>
  <head>
    <title>Simple example</title>
    <style type='text/css'>
        #sheet {
            border:1px solid black;
        }
    </style>
  </head>
  <body>
    <canvas id="sheet" width="400" height="400"></canvas>
    <script type='text/javascript'>
/*jslint browser:true */
"use strict";
var context = document.getElementById('sheet').getContext("2d");
var canvas = document.getElementById('sheet');
context = canvas.getContext("2d");
context.strokeStyle = "#ff0000";
context.lineJoin = "round";
context.lineWidth = 5;

var clickX = [];
var clickY = [];
var clickDrag = [];
var paint;

/**
 * Add information where the user clicked at.
 * @param {number} x
 * @param {number} y
 * @return {boolean} dragging
 */
function addClick(x, y, dragging) {
    clickX.push(x);
    clickY.push(y);
    clickDrag.push(dragging);
}

/**
 * Redraw the complete canvas.
 */
function redraw() {
    // Clears the canvas
    context.clearRect(0, 0, context.canvas.width, context.canvas.height);

    for (var i = 0; i < clickX.length; i += 1) {
        if (!clickDrag[i] && i == 0) {
            context.beginPath();
            context.moveTo(clickX[i], clickY[i]);
            context.stroke();
        } else if (!clickDrag[i] && i > 0) {
            context.closePath();

            context.beginPath();
            context.moveTo(clickX[i], clickY[i]);
            context.stroke();
        } else {
            context.lineTo(clickX[i], clickY[i]);
            context.stroke();
        }
    }
}

/**
 * Draw the newly added point.
 * @return {void}
 */
function drawNew() {
    var i = clickX.length - 1
    if (!clickDrag[i]) {
        if (clickX.length == 0) {
            context.beginPath();
            context.moveTo(clickX[i], clickY[i]);
            context.stroke();
        } else {
            context.closePath();

            context.beginPath();
            context.moveTo(clickX[i], clickY[i]);
            context.stroke();
        }
    } else {
        context.lineTo(clickX[i], clickY[i]);
        context.stroke();
    }
}

function mouseDownEventHandler(e) {
    paint = true;
    var x = e.pageX - canvas.offsetLeft;
    var y = e.pageY - canvas.offsetTop;
    if (paint) {
        addClick(x, y, false);
        drawNew();
    }
}

function touchstartEventHandler(e) {
    paint = true;
    if (paint) {
        addClick(e.touches[0].pageX - canvas.offsetLeft, e.touches[0].pageY - canvas.offsetTop, false);
        drawNew();
    }
}

function mouseUpEventHandler(e) {
    context.closePath();
    paint = false;
}

function mouseMoveEventHandler(e) {
    var x = e.pageX - canvas.offsetLeft;
    var y = e.pageY - canvas.offsetTop;
    if (paint) {
        addClick(x, y, true);
        drawNew();
    }
}

function touchMoveEventHandler(e) {
    if (paint) {
        addClick(e.touches[0].pageX - canvas.offsetLeft, e.touches[0].pageY - canvas.offsetTop, true);
        drawNew();
    }
}

function setUpHandler(isMouseandNotTouch, detectEvent) {
    removeRaceHandlers();
    if (isMouseandNotTouch) {
        canvas.addEventListener('mouseup', mouseUpEventHandler);
        canvas.addEventListener('mousemove', mouseMoveEventHandler);
        canvas.addEventListener('mousedown', mouseDownEventHandler);
        mouseDownEventHandler(detectEvent);
    } else {
        canvas.addEventListener('touchstart', touchstartEventHandler);
        canvas.addEventListener('touchmove', touchMoveEventHandler);
        canvas.addEventListener('touchend', mouseUpEventHandler);
        touchstartEventHandler(detectEvent);
    }
}

function mouseWins(e) {
    setUpHandler(true, e);
}

function touchWins(e) {
    setUpHandler(false, e);
}

function removeRaceHandlers() {
    canvas.removeEventListener('mousedown', mouseWins);
    canvas.removeEventListener('touchstart', touchWins);
}

canvas.addEventListener('mousedown', mouseWins);
canvas.addEventListener('touchstart', touchWins);
    </script>
  </body>
</html>

JSFiddle

  • la largeur des lignes peut être contrôlée avec context.lineWidth.
  • La couleur des lignes peut être contrôlé avec strokeStyle.

Cette solution fonctionne avec:

  • ordinateurs de Bureau:
    • Chrome 33
    • Firefox 28
  • Touch appareil:
    • Firefox 28 sur le Nexus 4

Il ne fonctionne pas avec

  • dispositifs tactiles:
    • Chrome 34 / Opera 20 sur Nexus 4 (Voir problème)

Importer / Exporter

importer et exporter l'image peut être fait en important / exportant clickX,clickY et clickDrag.

lissage de la ligne

Peut éventuellement être fait en remplaçant lineTo()bezierCurveTo()

6
répondu moose 2014-04-06 09:18:47

EaselJs

exemple Simple

A basic, complete example. That means it has to contain HTML 
and JavaScript. You can start with this:

<!DOCTYPE html>
<html>
<head>
    <title>EaselJS example</title>

    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/EaselJS/0.7.1/easeljs.min.js"></script>

    <script>
        var canvas, stage;
        var drawingCanvas;
        var oldPt;
        var oldMidPt;
        var color;
        var stroke;
        var index;

        function init() {
            if (window.top != window) {
                document.getElementById("header").style.display = "none";
            }
            canvas = document.getElementById("sheet");
            index = 0;

            //check to see if we are running in a browser with touch support
            stage = new createjs.Stage(canvas);
            stage.autoClear = false;
            stage.enableDOMEvents(true);

            createjs.Touch.enable(stage);
            createjs.Ticker.setFPS(24);

            drawingCanvas = new createjs.Shape();

            stage.addEventListener("stagemousedown", handleMouseDown);
            stage.addEventListener("stagemouseup", handleMouseUp);

            stage.addChild(drawingCanvas);
            stage.update();
        }

        function stop() {}

        function handleMouseDown(event) {
            color = "#ff0000";
            stroke = 5;
            oldPt = new createjs.Point(stage.mouseX, stage.mouseY);
            oldMidPt = oldPt;
            stage.addEventListener("stagemousemove" , handleMouseMove);
        }

        function handleMouseMove(event) {
            var midPt = new createjs.Point(oldPt.x + stage.mouseX>>1, oldPt.y+stage.mouseY>>1);

            drawingCanvas.graphics.clear().setStrokeStyle(stroke, 'round', 'round').beginStroke(color).moveTo(midPt.x, midPt.y).curveTo(oldPt.x, oldPt.y, oldMidPt.x, oldMidPt.y);

            oldPt.x = stage.mouseX;
            oldPt.y = stage.mouseY;

            oldMidPt.x = midPt.x;
            oldMidPt.y = midPt.y;

            stage.update();
        }

        function handleMouseUp(event) {
            stage.removeEventListener("stagemousemove" , handleMouseMove);
        }

    </script>
</head>
<body onload="init();">
    <canvas id="sheet" width="400" height="400"></canvas>
</body>
</html>

Démo

Les parties intéressantes dans la documentation sont les suivantes:

Cette solution fonctionne avec:

  • ordinateurs de Bureau:
    • Chrome 33
    • Firefox 28
  • dispositifs tactiles:
    • Chrome 34 / Firefox 28 / Opéra de 20 sur le Nexus 4

Importer / Exporter