Horje
Scratch Card Using React js

In this article, we will build a scratch card using ReactJS. A scratch card contains a reward; when the user scratches that card, the color present on the card will start erasing. And after erasing, the color content (reward) will be visible.

Preview:

Scratch-Card-Using-React-js

Prerequisite

Steps to Create the project:

  • Create a react application by using this command
npx create-react-app random-meal-generator
  • After creating your project folder, i.e. random-meal-generator, use the following command to navigate to it:
cd random-meal-generator

Project Structure

Package.json

"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}

Approach

  • InitializeCanvas: A gradient backdrop with randomly picked prize value is used to setup the first look of the scratch card.
  • checkIfTouchDevice: Check whether the user’s device is touch capable, and use different event handlers for touch and mouse devices.
  • getMouseCoordinates: Gets current mouse/touch coordinates in canvas’ space.
  • canvasElement: Detects dragging via mouse or touch, updates the scratch area.
  • scratch: Reveals the hidden content by erasing the top layer with destination-out global composite operation and updates the canvas based on the user’s interactions.
  • The useEffect hook is used to initialize the canvas of the scratch card. This canvas is initialized with the gradient filled background and with a hidden prize value. Users can use mouse or touch events to interact with the card.

Example:

CSS
* {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}

body {
    height: 100vh;
    background: #eee;
}

.container {
    position: absolute;
    transform: translate(-50%, -50%);
    top: 50%;
    left: 50%;
    border-radius: 0.6em;
}

.base,
#scratch {
    height: 200px;
    width: 200px;
    position: absolute;
    transform: translate(-50%, -50%);
    top: 50%;
    left: 50%;
    text-align: center;
    cursor: grabbing;
    border-radius: 2em;
}

.base {
    background-color: #ffffff;
    font-family: 'Poppins', sans-serif;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    box-shadow: 0 1.2em 2.5em rgba(16, 2, 96, 0.15);
}

.base h3 {
    font-weight: 600;
    font-size: 1.5em;
    color: #17013b;
}

.base h4 {
    font-weight: 400;
    color: #746e7e;
}

#scratch {
    -webkit-tap-highlight-color: transparent;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}
JavaScript
import React, { useEffect, useState } from "react";
import "./App.css";

const App = () => {
    const [prizeValue, setPrizeValue] = useState("$10"); // Default value

    useEffect(() => {
        const canvasElement = document.getElementById("scratch");
        const canvasContext = canvasElement.getContext("2d");
        let isDragging = false;

        const initializeCanvas = () => {
            const gradient = canvasContext.createLinearGradient(0, 0, 135, 135);
            gradient.addColorStop(0, "#d63031");
            gradient.addColorStop(1, "#fdcb6e");
            canvasContext.fillStyle = gradient;
            canvasContext.fillRect(0, 0, 200, 200);

            // Generate a random prize value from the available options
            const prizeOptions = [
                "$1", "$5", "$10", "$20", "$25", "$30", "$35", "$40", "$45", "$50"
            ];
            const randomPrize = prizeOptions[Math.floor(Math.random() * prizeOptions.length)];
            setPrizeValue(randomPrize);
        };

        const scratch = (x, y) => {
            canvasContext.globalCompositeOperation = "destination-out";
            canvasContext.beginPath();
            canvasContext.arc(x, y, 12, 0, 2 * Math.PI);
            canvasContext.fill();
        };

        const getMouseCoordinates = (event) => {
            const rect = canvasElement.getBoundingClientRect();
            const x = (event.pageX || event.touches[0].pageX) - rect.left;
            const y = (event.pageY || event.touches[0].pageY) - rect.top;
            return { x, y };
        };

        const handleMouseDown = (event) => {
            isDragging = true;
            const { x, y } = getMouseCoordinates(event);
            scratch(x, y);
        };

        const handleMouseMove = (event) => {
            if (isDragging) {
                event.preventDefault();
                const { x, y } = getMouseCoordinates(event);
                scratch(x, y);
            }
        };

        const handleMouseUp = () => {
            isDragging = false;
        };

        const handleMouseLeave = () => {
            isDragging = false;
        };

        const isTouchDevice = 'ontouchstart' in window;

        canvasElement.addEventListener(isTouchDevice ? "touchstart" : "mousedown", handleMouseDown);
        canvasElement.addEventListener(isTouchDevice ? "touchmove" : "mousemove", handleMouseMove);
        canvasElement.addEventListener(isTouchDevice ? "touchend" : "mouseup", handleMouseUp);
        canvasElement.addEventListener("mouseleave", handleMouseLeave);

        initializeCanvas();

        // Cleanup event listeners on unmount
        return () => {
            canvasElement.removeEventListener(isTouchDevice ? "touchstart" : "mousedown", handleMouseDown);
            canvasElement.removeEventListener(isTouchDevice ? "touchmove" : "mousemove", handleMouseMove);
            canvasElement.removeEventListener(isTouchDevice ? "touchend" : "mouseup", handleMouseUp);
            canvasElement.removeEventListener("mouseleave", handleMouseLeave);
        };
    }, []);

    return (
        <div className="container">
            <div className="base">
                <h4>You Won</h4>
                <h3>{prizeValue}</h3>
            </div>
            <canvas
                id="scratch"
                width="200"
                height="200"
                style={{
                    cursor: 'url("https://media.geeksforgeeks.org/wp-content/uploads/20231030101751/bx-eraser-icon.png"), auto'
                }}
            ></canvas>
        </div>
    );
};

export default App;
  • Type the following command in the terminal:
npm start
  • Type the following URL in the browser:
 http://localhost:3000/

Output:

mr-(2)





Reffered: https://www.geeksforgeeks.org


ReactJS

Related
Build a Language Translator App Using React Native Build a Language Translator App Using React Native
RGB Color Slider Using React js RGB Color Slider Using React js
Top React Native Apps to Build in 2024 Top React Native Apps to Build in 2024
React-Bootstrap Select React-Bootstrap Select
React-Bootstrap Range React-Bootstrap Range

Type:
Geek
Category:
Coding
Sub Category:
Tutorial
Uploaded by:
Admin
Views:
12