I've created an awesome painting app using React and Canvas API
Tags: showdev, react, webdev, javascript
Published: 2020-12-28 13:53:50

I've just submitted this app for [Hashnode Christmas hackathon](https://codeadrian.hashnode.dev/magic-painter-christmas-hackathon-project) so I wanted to talk about it here in more detail.

I didn't have a chance to work with HTML canvas and the [Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API), so this hackathon gave me a nice reason to dive right into it.

I also wanted to add something unique to make the result more **magic**, so I added a dynamic color brush and dynamic width brush. Turns out that this effect indeed looks more magic and dream-like.

## Tech stack

* React (with custom React hooks)
* Canvas API
* Native color picker and range inputs
* Font awesome icons
* Netlify hosting

## Intro screen

Since I'm primarily a frontend developer and I want to pay special attention to design and details, I've wanted to create a nice splash screen for the app. I was inspired by the watercolor and paint set box designs.

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1608976811117/CL16Du-xz.jpeg?auto=compress" />

I remember when I was buying paint sets for school, I was impressed by the images on the boxes. They showed a beautiful painting and were basically communicating "You can paint this beautiful image with this set". So I wanted to mimic that feeling with the splash screen.

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1609005716018/8JIbmAfvi.png?auto=compress" />

If you wonder how I managed to overlay a gradient on the heading text, here is a code snippet.

```css
  background: linear-gradient(
    90deg,
    hsl(0, 100%, 50%),
    hsl(211, 100%, 50%) 50%,
    hsl(108, 100%, 40%)
  );
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
```

## Custom hook
I've added the painting functionality with event listeners and Canvas API using a [custom hook](https://github.com/codeAdrian/react-magic-painter/blob/main/src/hooks/usePainter.ts) that returns a bunch of states and functions that are required for switching brushes, setting up a Canvas ref, and keeping track of active states.

## Dynamic color and brush width

This is where the magic happens. In the **magic brush mode**, I'm shifting the Hue value of HSL color for each paint event. The resulting effect is a wonderful color gradient. I've also added controls to change the color gradient saturation and lightness for more options and moods.

```js
ctx.current.strokeStyle = `hsl(${hue.current},${selectedSaturation.current}%,${selectedLightness.current}%)`;
ctx.current.globalCompositeOperation = "source-over";

hue.current++;

if (hue.current >= 360) hue.current = 0;
```

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1609006214515/iwOXw5iTu.gif?auto=format,compress&gif-q=60" />

Similar to the magic brush mode, I've also added a **dynamic width** mode that changes brush size value up and down between the minimum and maximum value. When combined with the **magic brush mode**, you can create some awesome art and effects.

```js
  const dynamicLineWidth = useCallback(() => {
    if (!ctx || !ctx.current) {
      return;
    }
    if (ctx.current.lineWidth > 90 || ctx.current.lineWidth < 10) {
      direction.current = !direction.current;
    }
    direction.current ? ctx.current.lineWidth++ : ctx.current.lineWidth--;
  }, []);
```

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1609006495646/QAxIniJc2.gif?auto=format,compress&gif-q=60" />

## App demo
https://magic-painter.netlify.app/

## Source code
{%github https://github.com/codeAdrian/react-magic-painter no-readme %}

## Post the art you create with the app in the comments! :)

If you enjoyed this post on my hackathon project for Hashnode, check out my hackathon project for DEV x DigitalOcean

{%link https://dev.to/adrianbdesigns/my-resolve-2021-do-hackathon-submission-91f %}

<hr />

These articles are fueled by coffee. So if you enjoy my work and found it useful, consider buying me a coffee! I would really appreciate it.

<a href="https://www.buymeacoffee.com/ubnZ8GgDJ" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-red.png" alt="Buy Me A Coffee" style="height: 51px !important;width: 217px !important;" ></a>

Thank you for taking the time to read this post. If you've found this useful, please give it a ❤️ or 🦄, share and comment.