How to Draw on Canvas and Save the Result Using Vanilla JavaScript

👋 Ciprian on Saturday, October 3, 2020 in Blog, JavaScript
Last modified on Friday, October 2, 2020

Learn JavaScript by example. Code snippets, how-to's and tutorials. Try now!

This was part of a complex drawing project, which is not relevant right now. The idea was to have a fully configurable canvas, where you could pick colours and sizes to write and draw anything.

I’m sure this has been done before, so I tried to keep my code to a minimum, while making sure the code has no dependencies and it’s modern and fast.

Here’s the HTML structure:

<div class="container">
    <canvas width="800%" height="400px" id="art"></canvas>
    <div id="buttons">
        <a id="reset">Restart</a>

        <div id="red" class="color"></div>
        <div id="blue" class="color"></div>
        <div id="green" class="color"></div>
        <div id="purple" class="color"></div>
        <div id="orange" class="color"></div>
        <div id="black" class="color"></div>
        <div id="white" class="color"></div>

        <div id="default" class="color">1</div>
        <div id="three" class="color">3</div>
        <div id="five" class="color">5</div>
        <div id="ten" class="color">10</div>
        <div id="fifteen" class="color">15</div>
        <div id="twenty" class="color">20</div>

        <a id="downloadLnk" class="color" href="#" download="illustration.png">Export</a>
    </div>
</div>

Here’s the CSS:

canvas {
    border: 1px solid #cbcbcb;
    background: #ecf0f1;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.25);
    cursor: crosshair;
}
.container {
    position: relative;
}
#buttons {
    position: absolute;
    top: 5px;
    left: 10px;
}
#reset {
    font-size: 24px;
    margin: 10px 10px 0 10px;
    float: left;
    cursor: pointer;
    color: #7f8c8d;
}
#downloadLnk {
    margin: 10px 10px 0 10px;
    color: #7f8c8d;
}
.color {
    color: #7f8c8d;
    width: 26px;
    height: 26px;
    line-height: 26px;
    float: left;
    margin: 10px 1px 0 0;
    cursor: pointer;
    text-align: center;
}
#red {
    background-color: #e74c3c;
}
#blue {
    background-color: #3498db;
}
#green {
    background-color: #2ecc71;
}
#purple {
    background-color: #9b59b6;
}
#orange {
    background-color: #f39c12;
}
#black {
    background-color: black;
}
#white {
    background-color: white;
}

And here’s the JavaScript functionality:

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

function getMousePos(canvas, evt) {
    let rect = canvas.getBoundingClientRect();
    return {
        x: evt.clientX - rect.left,
        y: evt.clientY - rect.top
    };
}

function mouseMove(evt) {
    let mousePos = getMousePos(canvas, evt);

    ctx.lineTo(mousePos.x, mousePos.y);
    ctx.stroke();
}

canvas.addEventListener('mousedown', (evt) => {
    let mousePos = getMousePos(canvas, evt);

    ctx.beginPath();
    ctx.moveTo(mousePos.x, mousePos.y);
    evt.preventDefault();
    canvas.addEventListener('mousemove', mouseMove, false);
});

canvas.addEventListener('mouseup', () => {
    canvas.removeEventListener('mousemove', mouseMove, false);
}, false);

document.getElementById('reset').addEventListener('click', () => {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
}, false);

const colors = ['red', 'blue', 'green', 'purple', 'orange', 'black', 'white'];
const size = [1, 3, 5, 10, 15, 20];
const sizeNames = ['default', 'three', 'five', 'ten', 'fifteen', 'twenty'];

function listener(i) {
    document.getElementById(colors[i]).addEventListener('click', () => {
        ctx.strokeStyle = colors[i];
    }, false);
}

function fontSizes(i) {
    document.getElementById(sizeNames[i]).addEventListener('click', () => {
        ctx.lineWidth = size[i];
    }, false);
}

for (let i = 0; i < colors.length; i++) {
    listener(i);
}

for (let i = 0; i < size.length; i++) {
    fontSizes(i);
}

document.getElementById('downloadLnk').addEventListener('click', () => {
    let image = canvas.toDataURL("image/png");
    this.href = image;
});

See a live demo here.

While I’m not particularly happy with the CSS and I know there’s room for improvement, the code is pretty fast and does the job. It’s also mobile compatible.

Find more JavaScript tutorials, code snippets and samples here or more jQuery tutorials, code snippets and samples here.

👋 Added by Ciprian on Saturday, October 3, 2020 in Blog, JavaScript. Last modified on Friday, October 2, 2020.

Leave a Reply

You have to agree to the comment policy.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Privacy Policy