Coloring HTML5 canvas regions on mouse over – Part 1

It’s gonna be about JS. Well, the blog name says MOSTLY Unity right? πŸ˜‰

Some time ago I had a client who had a very fun request. He wanted to be able to upload an image of a thing – let it be a piece of furniture or anything else – and while hovering over that image, the user would see a tooltip with information about the specific part he would be pointing at with his mouse. Fun, right? Long story short, after some tough negotiations I explained that given the timeframe it’s impossible or at least impossibly hard to make a component that would allow his company to upload just any image containing different colors, shapes etc. and create an algorithm that would recognize sections of that image in order for the client employees to label and describe them. I mean, yeah, we could probably achieve something with AI… Anyway, it all boiled down to uploading just a template that would contain only one color + transparency. Then my client would be able to mark a given section of that template as anything and everything.

In this (and the upcoming one) article, I will present you a minimal version of the code I used. In essence it’s just recognizing image sections and being able to color them while hovering over. Let’s start with this beautiful image of a bed with two pillows and sheet:

I believe that this basic html setup is self-explanatory, so I’ll just drop it here with no comments:

<html>
    <head>
        <script src="PixelMatrix.js"></script>
        <script src="PageManager.js"></script>
        <link rel="stylesheet" type="text/css" href="styles.css"> 

        <script>

            window.onload = () => {
                const manager = new PageManager('shape', 'file', '0075ed', '5b5b5b');
            };

        </script>
    </head>

    <body>
        <canvas 
            id="shape" 
            width="400" 
            height="400"></canvas>
        <input 
            type="file"
            id="file" 
            name="file"
            accept="image/png, image/jpeg" />
    </body>
</html>

Now to the JS code. I’ll start by describing the most interesting part of the PageManager class, but without going into too much detail. The reason for that is the fact that all of it can be easily found on the internet, so repeating it here would be a waste of space. Plus, the topic of this article(s) is THE ALGORITHM, not the basics of canvas element handling. I also won’t post the full JavaScript code here as the default wordpress source coloring is hideous (if you haven’t noticed the html code snippet above πŸ˜‰ ). The github URL to the full solution in attached in the bottom of this and the next article.

The below onCanvasHover method triggers when the user mouses-over the canvas element. In short, it finds the color (which is actually not a color, but a number – it should probably be called differently, but oh well…) of the region currently hovered over and marks it with the activeRegionColor which – to everyones surprise – actually is a color! πŸ™‚ Check it out:

onCanvasHover = (event) => {
        if (!this._activeRegionColor || !this._imageData) {
            return;
        }

        const coords = this._getCanvasCoords(event);
        const color = this._pixelMatrix.findColorAt(coords.x, coords.y);

        if (color === this._transparency) {
            return;
        }

        this.uncolorActiveRegion();

        const regionToColor = this._pixelMatrix.findRegionWithColor(color);

        for (let regionCoords of regionToColor) {
            const index = this._pixelIndex(regionCoords);

            this._imageData.data[index] = this._activeRegionColor.r;
            this._imageData.data[index + 1] = this._activeRegionColor.g;
            this._imageData.data[index + 2] = this._activeRegionColor.b;
            this._imageData.data[index + 3] = 255;
        }

        this._context.putImageData(this._imageData, 0, 0);

        this._lastColoredRegion = regionToColor;
    };

As you can see, it’s only canvas-specific logic without the actual algorithm being discussed. I think it was good idea to split the flood-fill algorithm implementation from the canvas-handling logic.

Yup, that would be it. I hope it was interesting enough to make you eager to read the rest πŸ˜‰

https://github.com/mostlyunity/flood-fill

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s