diff --git a/README.md b/README.md index 1841974..093b28b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,54 @@ -# Google Pay Scratch Card Demo +# Scratch & Win - Famous People Edition -### A simple scratch card similar to google pay reward cards +An interactive scratch card game featuring famous historical figures. Inspired by Google Pay reward cards, this modernized version includes random celebrity reveals, responsive design, and enhanced accessibility. -[View it live](https://grohit.com/scratchcard/) +## Features + +- **Random Celebrity Selection**: Each scratch reveals a different famous person from history +- **8 Historical Figures**: Albert Einstein, Marie Curie, Nelson Mandela, Leonardo da Vinci, Frida Kahlo, Mahatma Gandhi, Rosa Parks, and Stephen Hawking +- **Fully Responsive**: Works seamlessly on desktop, tablet, and mobile devices +- **Accessible**: ARIA labels, keyboard navigation, and screen reader support +- **Modern Design**: Gradient backgrounds, smooth animations, and polished UI +- **Error Handling**: Graceful fallbacks for image loading failures +- **Touch Optimized**: Perfect touch interactions for mobile devices + +## Technologies Used + +- HTML5 +- CSS3 (Flexbox, Grid, Modern Properties) +- JavaScript (ES6+) +- jQuery +- wScratchPad Plugin + +## How to Use + +1. Open `index.html` in a web browser +2. Use your mouse or finger to scratch the card surface +3. Reveal which famous person you've "won" +4. Click "Reset & Try Again" to get a new random celebrity + +## Improvements Over Original + +- Removed inline JavaScript (better code organization) +- Added multiple random celebrity images instead of static image +- Improved CSS with modern responsive design +- Enhanced accessibility (ARIA labels, semantic HTML) +- Added error handling and image preloading +- Removed duplicate files and broken links +- Added modern meta tags for SEO and social sharing +- Improved mobile responsiveness with better breakpoints +- Added smooth animations and transitions + +## Browser Support + +Works on all modern browsers: +- Chrome/Edge (latest) +- Firefox (latest) +- Safari (latest) +- Mobile browsers (iOS Safari, Chrome Mobile) + +## Credits + +Original concept: [G Rohit](https://grohit.com/) + +Enhanced and modernized by TRB diff --git a/css/style.css b/css/style.css index 19adbd2..31133ee 100644 --- a/css/style.css +++ b/css/style.css @@ -1,112 +1,249 @@ +/* CSS Reset & Base Styles */ +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + html { position: relative; min-height: 100%; + scroll-behavior: smooth; } body { font-family: 'Open Sans', sans-serif; - padding: 0; - margin: 0; - background: #eaeaea; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + background-attachment: fixed; + color: #333; + line-height: 1.6; + padding-bottom: 120px; } -.container{ - display: block; - margin: 0 auto; - height: 100%; +/* Header Styles */ +header { + position: sticky; + top: 0; + z-index: 100; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); } - -#scratchCard { - width: 500px; - height: 500px; - - display: block; - margin: 0 auto; - -} .title { font-family: 'IBM Plex Sans', sans-serif; text-transform: uppercase; text-align: center; - padding: 50px; + padding: 30px 20px; background-color: #121212; color: #ffffff; - margin-top: 0; + margin: 0; + font-size: clamp(1.5rem, 5vw, 2.5rem); + letter-spacing: 2px; + transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1); +} + +/* Main Container */ +.container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + max-width: 1200px; + margin: 0 auto; + padding: 40px 20px; + min-height: calc(100vh - 220px); +} + +/* Scratch Card Styles */ +#scratchCard { + width: min(500px, 90vw); + height: min(500px, 90vw); + display: block; + margin: 0 auto 30px; + border-radius: 20px; + box-shadow: 0 10px 50px rgba(0, 0, 0, 0.3); + overflow: hidden; + transition: transform 0.3s ease, box-shadow 0.3s ease; + touch-action: none; } -.btn { + +#scratchCard:hover { + transform: scale(1.02); + box-shadow: 0 15px 60px rgba(0, 0, 0, 0.4); +} + +#scratchCard canvas { + border-radius: 20px; +} + +/* Button Styles */ +.btn { -webkit-appearance: none; -moz-appearance: none; appearance: none; - width: 250px; - height: 50px; - border: none; - border-radius: 5px; - background: #5900ff; + width: min(250px, 90vw); + padding: 15px 30px; + border: 2px solid transparent; + border-radius: 50px; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #ffffff; cursor: pointer; - transition: 0.2s all ease; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); font-size: 1rem; -display: block; -margin: 50px auto; -text-align: center; + font-weight: 600; + font-family: 'IBM Plex Sans', sans-serif; + text-transform: uppercase; + letter-spacing: 1px; + display: block; + margin: 20px auto; + text-align: center; + box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4); } - .btn:hover { - border: 1px solid #5900ff; - background: #4400c4; - color: #ffffff; - box-shadow: 2px 2px 10px 0px #5900ff1f; - transition: 0.2s all ease; + transform: translateY(-2px); + box-shadow: 0 6px 25px rgba(102, 126, 234, 0.6); + background: linear-gradient(135deg, #764ba2 0%, #667eea 100%); } -.btn:focus { - outline: none; +.btn:active { + transform: translateY(0); + box-shadow: 0 2px 10px rgba(102, 126, 234, 0.4); } -.pageContentWrapper{ - margin-bottom:100px; - } +.btn:focus { + outline: 3px solid rgba(102, 126, 234, 0.5); + outline-offset: 2px; +} +/* No JavaScript Message */ +.no-js-message { + background: #fff3cd; + border: 2px solid #ffc107; + border-radius: 10px; + padding: 20px; + margin: 20px; + text-align: center; + font-weight: 600; + color: #856404; +} + +/* Page Content Wrapper */ +.pageContentWrapper { + margin-bottom: 120px; +} - a { +/* Link Styles */ +a { text-decoration: none; color: inherit; + transition: all 0.2s ease; } -a:hover{ +a:hover { text-decoration: underline; + opacity: 0.8; +} + +a:focus { + outline: 2px solid rgba(255, 255, 255, 0.5); + outline-offset: 2px; } +/* Footer Styles */ footer { text-align: center; - line-height: 100px; - background-color: #121212; - color: #ffffff; - position: absolute; - left: 0; - bottom: 0; - height: 100px; - width: 100%; - overflow: hidden; -} - -.goBack p{ - margin: 30px; - text-align: center; - font-size: 20px; + padding: 30px 20px; + background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%); + color: #ffffff; + position: absolute; + left: 0; + bottom: 0; + width: 100%; + box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.2); +} + +footer p { + margin: 0; + font-size: 0.95rem; +} + +footer a { + color: #667eea; + font-weight: 600; +} + +footer a:hover { + color: #764ba2; +} + +/* Loading Animation */ +@keyframes pulse { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } } - -@media all and (max-width:786px){ +.loading { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; +} + +/* Responsive Design */ +@media all and (max-width: 786px) { + .title { + padding: 20px 15px; + font-size: 1.5rem; + letter-spacing: 1px; + } + + #scratchCard { + width: min(350px, 90vw); + height: min(350px, 90vw); + margin-bottom: 20px; + } + + .container { + padding: 20px 15px; + min-height: calc(100vh - 180px); + } + + .btn { + width: min(200px, 85vw); + padding: 12px 25px; + font-size: 0.9rem; + } + + footer { + padding: 20px 15px; + font-size: 0.85rem; + } +} +@media all and (max-width: 480px) { #scratchCard { - width: 300px; - height: 300px; - - display: block; - margin: 0 auto; - + width: min(300px, 88vw); + height: min(300px, 88vw); + border-radius: 15px; + } + + .title { + font-size: 1.2rem; + } + + body { + padding-bottom: 100px; + } +} + +/* Print Styles */ +@media print { + header, footer, .btn { + display: none; + } + + body { + background: white; } } \ No newline at end of file diff --git a/images/google-scratch-card.jpg b/images/google-scratch-card.jpg index 4f8cd8d..0aa1c12 100644 Binary files a/images/google-scratch-card.jpg and b/images/google-scratch-card.jpg differ diff --git a/images/google-scratch-card.psd b/images/google-scratch-card.psd new file mode 100644 index 0000000..cccd94f Binary files /dev/null and b/images/google-scratch-card.psd differ diff --git a/images/winning-card.jpg b/images/winning-card.jpg deleted file mode 100644 index 9720527..0000000 Binary files a/images/winning-card.jpg and /dev/null differ diff --git a/index.html b/index.html index eef668c..fa31ea0 100644 --- a/index.html +++ b/index.html @@ -1,98 +1,78 @@ - + + - - - - - + - Scratch card like google pay | G Rohit - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + Scratch & Win - Famous People Edition | Interactive Game + + + + + + + + -

Scratch and win

-
+
+

Scratch and Win

+
-
+
+
+ + +
-
- +
-
+ + + - + - -
- - + + \ No newline at end of file diff --git a/js/main.js b/js/main.js index 231df06..63f733b 100644 --- a/js/main.js +++ b/js/main.js @@ -1,10 +1,183 @@ -$('#scratchCard').wScratchPad({ - size : 100, // The size of the brush/scratch. - bg : './images/winning-card.jpg', // Background (image path or hex color). - fg : './images/google-scratch-card.jpg', // Foreground (image path or hex color). - realtime : true, // Calculates percentage in realitime. - scratchDown : null, // Set scratchDown callback. - scratchUp : null, // Set scratchUp callback. - scratchMove : null, // Set scratcMove callback. - cursor : 'pointer' // Set cursor. - }); \ No newline at end of file +// Famous people prize images +const celebrities = [ + { + name: 'Albert Einstein', + image: 'https://via.placeholder.com/500x500/1a237e/ffffff?text=Albert+Einstein', + color: '#1a237e' + }, + { + name: 'Marie Curie', + image: 'https://via.placeholder.com/500x500/c2185b/ffffff?text=Marie+Curie', + color: '#c2185b' + }, + { + name: 'Nelson Mandela', + image: 'https://via.placeholder.com/500x500/1b5e20/ffffff?text=Nelson+Mandela', + color: '#1b5e20' + }, + { + name: 'Leonardo da Vinci', + image: 'https://via.placeholder.com/500x500/e65100/ffffff?text=Leonardo+da+Vinci', + color: '#e65100' + }, + { + name: 'Frida Kahlo', + image: 'https://via.placeholder.com/500x500/6a1b9a/ffffff?text=Frida+Kahlo', + color: '#6a1b9a' + }, + { + name: 'Mahatma Gandhi', + image: 'https://via.placeholder.com/500x500/004d40/ffffff?text=Mahatma+Gandhi', + color: '#004d40' + }, + { + name: 'Rosa Parks', + image: 'https://via.placeholder.com/500x500/b71c1c/ffffff?text=Rosa+Parks', + color: '#b71c1c' + }, + { + name: 'Stephen Hawking', + image: 'https://via.placeholder.com/500x500/01579b/ffffff?text=Stephen+Hawking', + color: '#01579b' + } +]; + +// Select a random celebrity +let selectedCelebrity = celebrities[Math.floor(Math.random() * celebrities.length)]; +let prizeRevealed = false; + +// Update the title with excitement +function updateTitle(name) { + const titleElement = document.querySelector('.title'); + if (titleElement) { + titleElement.textContent = `🎉 You Won: ${name}! 🎉`; + titleElement.style.background = `linear-gradient(135deg, ${selectedCelebrity.color}, #000)`; + } +} + +// Initialize scratch card with error handling +function initScratchCard() { + try { + // Check if required libraries are loaded + if (typeof $ === 'undefined') { + throw new Error('jQuery is not loaded'); + } + + if (typeof $.fn.wScratchPad === 'undefined') { + throw new Error('wScratchPad plugin is not loaded'); + } + + // Preload images before initializing + const bgImage = new Image(); + const fgImage = new Image(); + let imagesLoaded = 0; + + const checkImagesLoaded = () => { + imagesLoaded++; + if (imagesLoaded === 2) { + initializeScratchPad(); + } + }; + + bgImage.onload = checkImagesLoaded; + bgImage.onerror = () => { + console.warn('Background image failed to load, using fallback'); + checkImagesLoaded(); + }; + + fgImage.onload = checkImagesLoaded; + fgImage.onerror = () => { + console.warn('Foreground image failed to load, using fallback'); + checkImagesLoaded(); + }; + + bgImage.src = selectedCelebrity.image; + fgImage.src = './images/google-scratch-card.jpg'; + + function initializeScratchPad() { + $('#scratchCard').wScratchPad({ + size: 70, + bg: selectedCelebrity.image, + fg: './images/google-scratch-card.jpg', + realtime: true, + scratchDown: function(e, percent) { + console.log('Started scratching...'); + }, + scratchMove: function(e, percent) { + if (percent > 50 && !prizeRevealed) { + prizeRevealed = true; + this.clear(); + updateTitle(selectedCelebrity.name); + + // Add celebration animation + setTimeout(() => { + if (typeof confetti !== 'undefined') { + confetti(); + } + }, 300); + } + }, + scratchUp: function(e, percent) { + console.log('Scratch progress: ' + Math.round(percent) + '%'); + }, + cursor: 'pointer' + }); + } + } catch (error) { + console.error('Error initializing scratch card:', error); + showError('Failed to initialize scratch card. Please refresh the page.'); + } +} + +// Show error message to user +function showError(message) { + const errorDiv = document.createElement('div'); + errorDiv.className = 'error-message'; + errorDiv.style.cssText = ` + background: #f8d7da; + border: 2px solid #f5c6cb; + border-radius: 10px; + padding: 20px; + margin: 20px auto; + max-width: 500px; + text-align: center; + color: #721c24; + font-weight: 600; + `; + errorDiv.textContent = message; + document.querySelector('.container').prepend(errorDiv); +} + +// Initialize when DOM is ready +$(document).ready(function() { + initScratchCard(); + + // Add keyboard accessibility for reset button + $('.btn').on('keypress', function(e) { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + resetCard(); + } + }); +}); + +// Reset function +function resetCard() { + // Select a new random celebrity + selectedCelebrity = celebrities[Math.floor(Math.random() * celebrities.length)]; + prizeRevealed = false; + + // Reset the title + const titleElement = document.querySelector('.title'); + if (titleElement) { + titleElement.textContent = 'Scratch and Win'; + titleElement.style.background = '#121212'; + } + + // Reset the scratch card + $('#scratchCard').wScratchPad('reset'); + + // Reinitialize with new celebrity + $('#scratchCard').wScratchPad('destroy'); + initScratchCard(); +} \ No newline at end of file