Building the Magic Wand Tool for a Drawing App, pt. 1

Tom Cantwell
2 min readApr 23, 2021

In my drawing app, Pixel V, I have a color replace tool that lets you restrict where the brush makes a mark to only a chosen color. When the brush was limited to a single pixel width, I just checked the canvas for the color of the pixel at the coordinates of the brush. Once I increased the brush size, this method was no longer practical, and I had to find a new method. The new method I found was to clip the area that had a certain color, thus only allowing the user to draw over the chosen color. This marks the beginnings of building a select tool or magic wand tool, where you manipulate a certain area of the drawing.

This new implementation ultimately allowed me to entirely get rid of the replace action, and re-use some existing code. Here’s the new replaceSteps function that controls the event steps of the replace tool:

The main thing we’ll focus on is this function, createClipMask.

Using the built in API, Path2D, we can save a path for later use. The other way is to use beginPath but any path we make would be completely lost when we restore the context. Using Path2D isn’t strictly necessary for the current state of this tool, but it’s cleaner and has more potential for growth once we start making things more complicated. With a Path2D object, we can add other paths to it to make one big path. That’s exactly what I’m doing here, adding a 1 pixel rectangle to the path for each pixel to be part of the desired drawing area. This is an expensive operation, but it’s only called on mousedown, and then allows any replacing to happen just as smoothly as normal drawing. Once we have the path, we call context.clip(clipMask) on line 1018 to restrict drawing to the clipped area. To build this out further, next time we’ll add another path around the perimeter of the clipped area that we will stroke and animate to improve user experience for a magic wand tool.