From 86e2db9a3d66a4bba5f9942127b03d091bde9d32 Mon Sep 17 00:00:00 2001 From: tomas Date: Wed, 9 Oct 2024 18:14:57 +0100 Subject: [PATCH] add /present --- public/media/qr-website.png | Bin 0 -> 5760 bytes src/Pages/Present.tsx | 112 ++++++++++++++++++++++++++++++++++++ src/main.tsx | 2 + 3 files changed, 114 insertions(+) create mode 100644 public/media/qr-website.png create mode 100644 src/Pages/Present.tsx diff --git a/public/media/qr-website.png b/public/media/qr-website.png new file mode 100644 index 0000000000000000000000000000000000000000..feea57b6c64531e00ea5a69503027a9ad13e4e30 GIT binary patch literal 5760 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 { + const canvasRef = useRef(null) + const [isMoving, setIsMoving] = useState(true) + + useEffect(() => { + const canvas = canvasRef.current + if (!canvas) return + + const ctx = canvas.getContext('2d') + if (!ctx) return + + // Set up high DPI canvas + const dpr = window.devicePixelRatio || 1 + const rect = canvas.getBoundingClientRect() + + canvas.width = rect.width * dpr + canvas.height = rect.height * dpr + canvas.style.width = `${rect.width}px` + canvas.style.height = `${rect.height}px` + + ctx.scale(dpr, dpr) + + const qrCode = new Image() + qrCode.src = qrCodeImage + + let x = rect.width / 2 - 150 + let y = rect.height / 2 - 150 + let dx = 0.5 + let dy = 0.5 + const size = 300 + + const animate = () => { + if (!ctx) return + + ctx.clearRect(0, 0, rect.width, rect.height) + + // Create gradient background + const gradient = ctx.createLinearGradient(0, 0, rect.width, rect.height) + gradient.addColorStop(0, '#8A2BE2') // Purple + gradient.addColorStop(1, '#CAA0FF') // White + ctx.fillStyle = gradient + ctx.fillRect(0, 0, rect.width, rect.height) + + // Draw QR code + ctx.drawImage(qrCode, x, y, size, size) + + if (isMoving) { + // Update position + x += dx + y += dy + + // Bounce off walls + if (x + size > rect.width || x < 0) dx = -dx + if (y + size > rect.height || y < 0) dy = -dy + } + + requestAnimationFrame(animate) + } + + qrCode.onload = animate + + // Resize canvas on window resize + const handleResize = () => { + const newRect = canvas.getBoundingClientRect() + canvas.width = newRect.width * dpr + canvas.height = newRect.height * dpr + canvas.style.width = `${newRect.width}px` + canvas.style.height = `${newRect.height}px` + ctx.scale(dpr, dpr) + x = newRect.width / 2 - 150 + y = newRect.height / 2 - 150 + } + + window.addEventListener('resize', handleResize) + + // Handle spacebar press + const handleKeyPress = (event: KeyboardEvent) => { + if (event.code === 'Space') { + if (isMoving) { + x = rect.width / 2 - 150 + y = rect.height / 2 - 150 + } + setIsMoving(!isMoving) + } + } + + window.addEventListener('keydown', handleKeyPress) + + return () => { + window.removeEventListener('resize', handleResize) + window.removeEventListener('keydown', handleKeyPress) + } + }, [isMoving]) + + return ( + + ) +} + +export default Present diff --git a/src/main.tsx b/src/main.tsx index 87d4201..ece3b18 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -11,6 +11,7 @@ import Components from './Pages/Components' import ScrollToTop from './components/ScrollToTop' import Navbar from './Header/Navbar' import About from './Pages/About' +import Present from './Pages/Present' ReactDOM.render( @@ -23,6 +24,7 @@ ReactDOM.render( } /> } /> } /> + } /> // Add this line ,