Digital Scratch Card HTML CSS JavaScript

 

Interactive Scratch Card Coupon Reveal: A Web Development Deep Dive

Creating engaging user experiences is essential for modern web applications, especially in e-commerce and promotional contexts. Today, I’ll walk through an interactive scratch card coupon system that lets users reveal discount codes through a familiar and satisfying scratching interaction.

Project Overview

This project implements a digital “scratch to reveal” experience similar to physical scratch cards. Users can use their mouse (or finger on touch devices) to scratch away a surface layer, gradually revealing a discount code underneath. The system includes a progress bar that tracks how much of the card has been scratched, with automatic full reveal once a threshold is reached.

Key Components

1. HTML Structure

The foundation is a clean HTML structure that contains:

  • A heading and instruction text
  • A container for the scratch card with the hidden coupon code
  • A canvas element that serves as the scratchable surface
  • A progress bar to track completion
  • A reset button to start over

2. Visual Styling with CSS

The CSS provides a polished, modern look with:

  • A card-like container with subtle shadows
  • A vibrant gradient background for the coupon code
  • Responsive design elements that work across devices
  • Smooth transitions for the progress indicator

3. Interactive JavaScript Functionality

The core functionality is implemented in JavaScript with these key features:

function scratch(x, y) {
ctx.globalCompositeOperation = 'destination-out';
ctx.beginPath();
ctx.arc(x, y, scratchRadius, 0, Math.PI * 2);
ctx.fill();

// Track which pixels have been scratched
const minX = Math.max(0, Math.floor(x - scratchRadius));
const maxX = Math.min(canvas.width, Math.ceil(x + scratchRadius));
const minY = Math.max(0, Math.floor(y - scratchRadius));
const maxY = Math.min(canvas.height, Math.ceil(y + scratchRadius));
for (let i = minX; i < maxX; i++) {
for (let j = minY; j < maxY; j++) {
const dx = i - x;
const dy = j - y;
if (dx * dx + dy * dy <= scratchRadius * scratchRadius) {
scratchedPixels[j * canvas.width + i] = true;
}
}
}

updateProgress();
}

This function creates the scratch effect at the cursor position and tracks which pixels have been scratched to update the progress bar.

Technical Implementation Details

Canvas Initialization

The scratch surface is created using an HTML5 Canvas with a subtle gradient and tiny random speckles that mimic the texture of a real scratch card:

function initCanvas() {
const gradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
gradient.addColorStop(0, '#ccc');
gradient.addColorStop(0.5, '#ddd');
gradient.addColorStop(1, '#bbb');
ctx.globalCompositeOperation = 'source-over';
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);

// Add texture with random dots
for (let i = 0; i < 5000; i++) {
const x = Math.random() * canvas.width;
const y = Math.random() * canvas.height;
const radius = Math.random() * 1.5;
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fillStyle = Math.random() > 0.5 ? '#c5c5c5' : '#d5d5d5';
ctx.fill();
}

// Reset tracking variables
scratchedCount = 0;
scratchedPixels.fill(false);
progressBar.style.width = '0%';
scratchText.style.display = 'block';
}

Progress Tracking

The system keeps track of how much of the card has been scratched and automatically completes the reveal once a threshold (50% by default) is reached:

function updateProgress() {
scratchedCount = scratchedPixels.filter(Boolean).length;
const percentage = (scratchedCount / totalPixels) * 100;
progressBar.style.width = `${percentage}%`;

if (percentage >= revealThreshold * 100) {
// If more than the threshold is scratched, clear the scratch layer completely
ctx.clearRect(0, 0, canvas.width, canvas.height);
scratchText.style.display = 'none';
progressBar.style.width = '100%';
}
}

Touch and Mouse Support

The implementation handles both mouse and touch interactions, ensuring the experience works well across desktop and mobile devices with smooth scratch paths:

canvas.addEventListener('touchmove', (e) => {
e.preventDefault();
if (!isDrawing) return;
const rect = canvas.getBoundingClientRect();
const touch = e.touches[0];
const currentX = touch.clientX - rect.left;
const currentY = touch.clientY - rect.top;

const dx = currentX - lastX;
const dy = currentY - lastY;
const distance = Math.max(Math.abs(dx), Math.abs(dy));
for (let i = 0; i < distance; i++) {
const x = lastX + (dx * i) / distance;
const y = lastY + (dy * i) / distance;
scratch(x, y);
}

lastX = currentX;
lastY = currentY;
});

Use Cases and Extensions

This scratch card system is perfect for:

  • Revealing discount codes in e-commerce
  • Promotional campaigns for product launches
  • Reward systems in customer loyalty programs
  • Interactive newsletters and marketing materials

The code could be extended to include:

  • Variable reward values with different probabilities
  • Server-side validation of revealed codes
  • Confetti animations upon full reveal
  • Time-limited codes that expire

Conclusion

This scratch card implementation demonstrates how modern web technologies can create engaging, interactive experiences that delight users while serving marketing goals. The combination of canvas drawing, event handling, and visual feedback creates a satisfying interaction that mimics physical scratch cards while providing the benefits of digital tracking and instant reward delivery.

Comments