Рисование на холсте HTML5 с помощью мыши

Я хочу рисовать на холсте HTML с помощью мыши (например, нарисовать подпись, нарисовать имя и т.д.)

Как мне это реализовать?

Свободный перевод вопроса Draw on HTML5 Canvas using a mouse от участника @MartinJoo.


Ответы (2 шт):

Автор решения: Alexandr_TT

Вот рабочий пример:

Разверните сниппет на полный экран

<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.

→ Ссылка
Автор решения: Leonid

На скоро можно так. Для стирания выбрать белый цвет и соответствующий размер кисти. Скачивание изображения через динамическое создание ссылки почему то в здесь в сниппете не работает, но браузеры уже давно добавили опцию "Сохранить картинку как..." по rightClick для canvas, а потому дублировать в виде изображения не имеет смысла.

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

const w = canvas.width = 400;
const h = canvas.height = 400;

const color_inp = document.querySelector('input[type="color"]');
const width_inp = document.querySelector('input[type="range"]');
const clear_button = document.querySelector('#clear');

ctx.lineCap = 'round';

color_inp.addEventListener('change', changeColor);
width_inp.addEventListener('change', changeLineWidth);
clear_button.addEventListener('click', clearCanvas);

let path = '';
let is_mouse_down = false;

canvas.addEventListener('mousedown', beginPath);
canvas.addEventListener('mousemove', extendPath);
canvas.addEventListener('mouseup', endPath);
canvas.addEventListener('mouseleave', endPath);

function beginPath(e) {
  path = `M ${e.offsetX} ${e.offsetY} L `;
  is_mouse_down = true;
}

function extendPath(e) {
  if (is_mouse_down) {
    path += `${e.offsetX} ${e.offsetY} `;
    draw();
    path = `M ${e.offsetX} ${e.offsetY} L `;
  }
}

function endPath(e) {
  path += `${e.offsetX} ${e.offsetY} `;
  draw();
  path = '';
  is_mouse_down = false;
}

function draw() {
  ctx.stroke(new Path2D(path));
}

function changeColor(event) {
  ctx.strokeStyle = event.target.value;
}

function changeLineWidth(event) {
  ctx.lineWidth = +event.target.value;
}

function clearCanvas() {
  ctx.clearRect(0, 0, w, h);
}
<canvas style="border: 1px solid black"></canvas>
<div style="display: flex; justify-content: space-between; width: 400px">
    <input type="color">
    <input type="range" min="1" max="50" step="1" value="1">
    <button type="button" id="clear">Clear</button>
</div>

→ Ссылка