Tutorial

Drawing Creative Brushstrokes with JavaScript

Draft updated on Invalid Date
Default avatar

By Luis Manuel

Drawing Creative Brushstrokes with JavaScript

This tutorial is out of date and no longer maintained.

Introduction

Some time ago I see this fun demo in Codepen, by Akimitsu Hamamuro. Then I think that it would be great to be able to draw things programmatically in the web. Unfortunately, I could not find any library to do it, so I’ve developed one, using that pen as base.

In this tutorial, we’ll see how to use this new library to draw creative brushstrokes directly in the browser with a nice API. We’ll be able to draw solid colors, images, or even HTML!

Specifically, we will be learning how to build a creative poster like this:

Getting Started

Getting started with the Brushstroke library is pretty simple. You only need to include the script and start drawing things:

<!-- Optional dependencies goes here -->
<script src="dist/brushstroke.min.js"></script>
<script>
    // Options for customization
    var options = {
        duration: 1,
        queue: true
    };

    // Initialization
    var bs = new Brushstroke(options);

    // Draw, erase, etc...
    bs.draw();
    bs.erase();
    bs.draw();
</script>

This is just a very basic example. You can find detailed documentation in the GitHub repo.

Drawing the Background Image

As you may see, our poster consists of a background image and text. Let’s see how to animate the drawing of the background image.

First, we need to initialize a new Brushstroke instance for the background image, with all the options we want. Please learn more about each option in the GitHub repo.

// Declaring variables

var width = window.innerWidth || document.body.clientWidth;
var height = window.innerHeight || document.body.clientHeight;
var optionsBackground, bsBackground;

// Random curves for background

optionsBackground = {
    animation: 'points',
    points: 10,
    inkAmount: 5,
    size: 300,
    frames: 10,
    frameAnimation: true,
    splashing: false,
    image: 'images/background.jpg',
    centered: true,
    queue: true,
    width: width,
    height: height
};
bsBackground = new Brushstroke(optionsBackground);

Now we can start drawing things, and more!

Let’s see how to achieve the effect we want for our poster:

// Function to start the animation

function runAnimation() {
    // Draw a straight line
    bsBackground.draw({
        points: [0, height / 2 - 40, width, height / 3]
    });

    // Draw another straight line
    bsBackground.draw({
        points: [width, height / 2, 0, height / 1.5 - 40]
    });

    // Draw a curve generated using 20 random points
    bsBackground.draw({
        inkAmount: 3,
        frames: 100,
        size: 200,
        splashing: true,
        points: 20
    });
}

// Start

runAnimation();

Drawing the Text

Our library is not able to draw text as is, but it can draw along any SVG path provided. So we can draw our text as SVG paths, and then we can pass the paths to the library.

After render, scale up, and simplify the paths (CTRL+L) to create smother shapes of our text, our SVG looks like this:

Now we have our text as single-stroke SVG paths, and we can use them to draw with the Brushstroke library!

First, we need to include the SVG in the HTML:

<!-- Each path is a letter in "Scotch.io" string -->
<svg width="1000" height="300" style="display: none">
    <path d="m157.76 105.88c-7.4053-8.9862-16.122-15.85-27.865-17.818-16.604-3.2803-35.244-2.2435-50.148 6.2719-8.4329 6.4228-15.194 15.018-10.757 25.919 6.9636 23.286 33.81 26.063 53.267 33.499 15.84 4.0064 32.554 13.238 35.503 30.658 1.8468 11.869-0.78168 21.884-11.233 28.659-14.576 8.9259-33.167 9.5932-49.689 6.8414-12.29-2.3318-20.767-8.5079-28.636-18.075"/>
    <path d="m272.9 150.66c-9.8598-11.768-23.423-22.368-39.709-19.191-13.362 0.5304-25.61 11.328-31.775 22.54-6.7138 13.934-7.1853 29.748-0.25697 43.707 5.5237 11.364 17.648 21.717 30.492 23.311 15.813 2.8302 30.126-5.4593 39.688-17.63l1.2482-1.2482 0.31262-0.31262"/>
    <path d="m343.27 131.47c-15.039 5.7827-27.96 17.873-30.612 34.262-4.0296 12.888 0.41254 27.839 7.52 38.602 9.0267 11.179 22.414 19.394 37.213 16.695 13.362-0.53038 25.61-11.328 31.775-22.54 6.7139-13.934 7.1853-29.748 0.25697-43.707-5.5237-11.364-17.648-21.717-30.492-23.311h-15.661z"/>
    <path d="m445.62 86.692c0.37493 36.778-0.74805 73.798 0.55819 110.42 2.5876 11.039 6.138 21.243 18.469 23.832 4.2802 0.18855 8.6454 0.0288 12.958 0.0819m-51.176-89.559h44.779"/>
    <path d="m586.36 150.66c-9.8598-11.768-23.423-22.368-39.709-19.191-13.362 0.5304-25.61 11.328-31.775 22.54-6.7139 13.934-7.1853 29.748-0.25697 43.707 5.5237 11.364 17.648 21.717 30.492 23.311 15.813 2.8302 30.126-5.4593 39.688-17.63l1.2482-1.2482 0.31262-0.31262"/>
    <path d="m631.14 86.692v134.34m0-63.971c12.158-12.114 24.92-29.2 44.341-25.588 10.207-0.53645 22.347 4.9455 22.978 16.444 6.3533 18.657 1.559 39.122 3.0479 58.568v14.546"/>
    <path d="m752.68 189.04c-15.025 6.5899 6.2843 18.544 5.1489 5.1489l-5.1489-5.1489z"/>
    <path d="m797.46 86.692c6.5899 15.025 18.544-6.2843 5.1489-5.1489l-5.1489 5.1489zm6.3971 44.779v89.559"/>
    <path d="m880.62 131.47c-15.039 5.7827-27.96 17.873-30.612 34.262-4.0295 12.888 0.41253 27.839 7.52 38.602 9.0268 11.179 22.414 19.394 37.213 16.695 13.362-0.53038 25.61-11.328 31.775-22.54 6.7139-13.934 7.1853-29.748 0.25697-43.707-5.5237-11.364-17.648-21.717-30.492-23.311h-15.661z"/>
</svg>

Then we can use those SVG paths in our library to draw the text:

// Declaring variables

var optionsPath, bsPath;

// Options for text (SVG paths)

optionsPath = {
    animation: 'path',
    inkAmount: 2,
    frames: 20,
    frameAnimation: true,
    color: 'white',
    width: 1000,
    height: 300
};

// Initializing

bsPath = new Brushstroke(optionsPath);

// Draw each letter of the text, with a delay among them

var paths = document.querySelectorAll('path');
var delay = 0;

for (var i = 0; i < paths.length; i++) {
    bsPath.draw({path: paths[i], delay: delay});
    delay += 0.5;
}

Adding “Run Again” Functionality

Finally, we’d like to provide an option to repeat the animation in our poster, so we can see it again and again.

The idea is to draw the entire screen with a solid black color (like erasing), and then run our poster animation again. Let’s see the implementation:

// Declaring variables

var button = document.querySelector('button');
var animating = true;
var optionsErase, bsErase;


// Erase and run again

optionsErase = {
    queue: true,
    size: 300,
    padding: 0,
    overlap: 100,
    inkAmount: 20,
    frames: 100,
    frameAnimation: true,
    color: '#000',
    width: width,
    height: height,
    end: function () {
        // Clear all canvas and run animation
        bsBackground.clear();
        bsPath.clear();
        bsErase.clear();
        runAnimation();
    }
};
bsErase = new Brushstroke(optionsErase);


// Run again button

button.addEventListener('click', function () {
    if (!animating) {
        toggleButton();
        bsErase.draw();
    }
});

function toggleButton() {
    button.classList.toggle('hidden');
    animating = !animating;
}

Conclusion

And that’s all!

With a bit of styling to get things in the right place, we should have a beautiful and creative poster using brushstroke animations :)

As always, you can check the final demo here, and also get the full code and documentation on GitHub. There are more exciting features waiting for you there!

We really hope you liked this tutorial and find it useful!

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
Luis Manuel

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel