How to Create a Color Picker App using React.js and Canvas element

Saurabh Mhatre
8 min readFeb 11, 2024

--

Title image

In this blog post, I will show you how to create a simple color picker app using React.js and Tailwind css. A color picker app is a useful tool that allows you to select a color from an image and get its hex code. You can use this app to find the perfect color for your design, website, or project.

Introduction

To create this app, we will use the following technologies:

- React.js: A popular JavaScript library for building user interfaces.
- Tailwind css: A utility-first CSS framework that provides a set of ready-made classes for styling elements.
- Canvas: A HTML element that allows us to draw graphics on the web page.

The app will have the following features:

- A file input that allows the user to upload an image.
- A canvas that displays the uploaded image and responds to the user's click or tap events.
- A text that shows the hex color code of the selected pixel on the image.

App demo:

Color picker demo

Steps

To create this app, we will follow these steps:

1. Set up the project and install the dependencies.
2. Create the main app component and the file input.
3. Create the color picker component and the canvas.
4. Add the logic for getting the pixel data and the hex color code.
5. Create the header component and style the app using Tailwind css.

Step 1: Set up the project

First, we need to set up the project:

To do this, run the following commands in your terminal:

# Create a new React project
npx create-react-app color-picker-app

# Change the directory to the project folder
cd color-picker-app

Step 2: Create the main app component and the file input

Next, we need to create the main app component and the file input. The main app component will be responsible for rendering the app and managing the state. The file input will allow the user to upload an image and display it on the canvas.

To create the main app component, open the src/App.js file and replace its content with the following code:

// Import React and Tailwind css
import React, { useState } from "react";
import Header from "./Header";
import ColorPicker from "./ColorPicker";
import "./styles.css";

// Define the main app component
function App() {
// Use a state to store the image source
const [image, setImage] = useState(null);

// Define a function to handle the file input change event
const handleChange = (e) => {
// Get the selected file
const file = e.target.files[0];

// Check if the file is an image
if (file && file.type.startsWith("image/")) {
// Create a URL for the file
const url = URL.createObjectURL(file);

// Create a new image object
const img = new Image();

// Set the image source to the URL
img.src = url;

// Set the image state to the image object
img.onload = () => {
// Set the image state to the image object
setImage(img);
};
}
};

// Render the app
return (
<div className="app">
<Header/>
<div className="app-body">
<input type="file" accept="image/*" onChange={handleChange} />
{image && <ColorPicker image={image} />}
</div>
</div>
);
}

// Export the app component
export default App;

In this code, we do the following things:

  • Use the useState hook to create a state variable called `image` and a setter function called `setImage`. The initial value of the state is null.
  • Define a function called `handleChange` that takes an event object as an argument. This function will handle the change event of the file input.
  • In the `handleChange` function, we do the following things:
    Get the selected file from the event target using the files property.
    Check if the file is an image by using the type property and the startsWith method.If the file is an image, we do the following things:
    Create a URL for the file using the URL.createObjectURL method. This method creates a temporary URL that points to the file object in memory.
    Create a new image object using the Image constructor. This object represents an HTML image element.
    Set the image source to the URL using the src property.
    Set the image state to the image object using the setImage function
  • After the input element, render a conditional expression that checks if the image state is not null. If so, render the ColorPicker component and pass the image state as a prop. The ColorPicker component will be created in the next step.

Step 3: Create the color picker component and the canvas

Next, we need to create the color picker component and the canvas. The color picker component will be responsible for rendering the canvas and the color code. The canvas will display the uploaded image and respond to the user’s click or tap events.

To create the color picker component, create a new file called src/ColorPicker.js and add the following code:

// Import React and Tailwind css
import React, { useState, useRef } from "react";

// Define a custom component for the color picker
function ColorPicker({ image }) {
// Use a ref to access the canvas element
const canvasRef = useRef(null);

// Use a state to store the selected color
const [color, setColor] = useState("#ffffff");

// Define a function to handle the click or tap event on the canvas
const handleClick = (e) => {
// Get the canvas context
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");

// Get the mouse or touch position relative to the canvas
const rect = canvas.getBoundingClientRect();
const x = Math.round(e.clientX - rect.left);
const y = Math.round(e.clientY - rect.top);
if(x && y) {
// Get the pixel data at the position
const pixel = ctx.getImageData(x, y, 1, 1).data;

// Convert the pixel data to a hex color code
const hex = "#" + ("000000" + rgbToHex(pixel[0], pixel[1], pixel[2])).slice(-6);

// Update the color state
setColor(hex);
}
};

// Define a helper function to convert RGB values to hex
const rgbToHex = (r, g, b) => {
if (r > 255 || g > 255 || b > 255) throw "Invalid color component";
return ((r << 16) | (g << 8) | b).toString(16);
};

// Define a function to draw the image on the canvas
const drawImage = () => {
// Get the canvas context
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");

// Draw the image on the canvas
ctx.drawImage(image, 0, 0, image.width, image.height);
};

// Use an effect to draw the image when the component mounts
useEffect(() => {
drawImage();
}, [image]);

// Render the canvas and the color code
return (
<div className="color-picker">
<canvas
ref={canvasRef}
width={image.width}
height={image.height}
onClick={handleClick}
onTouchEnd={handleClick}
/>
<p className="color-code">{color}</p>
</div>
);
}

// Export the color picker component
export default ColorPicker;

In this code, we do the following things:

  • Use the useRef hook to create a ref variable called canvasRef and assign it to the canvas element. This will allow us to access the canvas element and its properties in the code.
  • Use the useState hook to create a state variable called color and a setter function called setColor. The initial value of the state is #ffffff, which represents white color.
  • Define a function called handleClick that takes an event object as an argument. This function will handle the click or tap event on the canvas.
  • In the handleClick function, we do the following things:
    Get the canvas element and the canvas context from the canvasRef using the current property and the getContext method. The canvas context is an object that provides methods and properties for drawing on the canvas.
    Get the mouse or touch position relative to the canvas using the clientX and clientY properties of the event object and the getBoundingClientRect method of the canvas element. The getBoundingClientRect method returns the size and position of the canvas element relative to the viewport. Round the position values to the nearest integer using the Math.round function. This is because the getImageData method expects integer arguments.
    Get the pixel data at the position using the getImageData method of the canvas context. This method returns an object that contains the RGBA values of the pixel in an array. The RGBA values are numbers between 0 and 255 that represent the red, green, blue, and alpha (transparency) components of the color. Convert the pixel data to a hex color code using a helper function called rgbToHex. This function takes the RGB values as arguments and returns a string that represents the hex color code. The hex color code is a six-digit hexadecimal number that represents the color. For example, #ffffff is the hex color code for white.
    Update the color state to the hex color code using the setColor function.
  • Define a function called drawImage that draws the image on the canvas. This function does the following things:
    Get the canvas element and the canvas context from the canvasRef using the current property and the getContext method.
    Draw the image on the canvas using the drawImage method of the canvas context. This method takes an image object as an argument and draws it on the canvas. The image object is the same as the image prop that we passed to the color picker component.
  • Use the useEffect hook to run the drawImage function when the component mounts. The useEffect hook takes a function and an array of dependencies as arguments and runs the function after the component renders. The array of dependencies tells React when to run the function again.
  • After the canvas element, render a p element with a class name of color-code and the color state as the text content. This will display the hex color code of the selected pixel on the image.

Step 5: Create the header component

To create the header component, create a new file called src/Header.js and add the following code:

// Import React and Tailwind css
import React from "react"


// Define a custom component for the header
function Header() {
// Render the header
return (
<div className="header bg-blue-500">
<div className="container mx-auto flex items-center justify-between py-4">
<div className="title text-white text-2xl font-bold">
Color Picker
</div>
</div>
</div>
);
}

// Export the header component
export default Header;

Styling the app:

Add below tailwindcss script in public/index.html file to integrate Tailwindcss in the project:

  <script src="https://cdn.tailwindcss.com"></script>

We can test the app by opening the browser and see the app with the new styles.

Live Demo: StackBlitz

Conclusion

In this blog post, we have learned how to create a color picker app using React.js and Tailwind css. We have used the following technologies and concepts:
Canvas: A HTML element that allows us to draw graphics on the web page.

Ref: A way of accessing and modifying DOM elements in React components
I hope you enjoyed this blog post and learned something new. If you have any questions or feedback, please let me know in the comments section below. Thank you for reading. Have a nice day ahead 😁

Don’t forget to subscribe to my YouTube channel for more content:

SaurabhNative--Youtube

--

--