Musíte změnit nastavení vašeho prohlížeče
Podívejte se na:
Jak povolit JavaScript ve vašem prohlížeči
.
Pokud používáte software na blokování reklam, může být nutné povolit JavaScript z této stránky.
Děkujeme.
K personalizaci obsahu a reklam, poskytování funkcí sociálních médií a analýze naší návštěvnosti využíváme soubory cookies. Více informací
zde
.
Nastavení
Odmítnout
Souhlasím
Přejít na obsah
Zpět
do obchodu
Přihlášení k vašemu účtu
Nemůžete vyplnit toto pole
Přihlásit se
Nová registrace
Zapomenuté heslo
Váš nákupní košík je prázdný
Podívejte se na naši nabídku
rok
měsíc
týden
tracker
prázdné listy
desky
komplet
Zkuste vyhledávání
Hledat
'use client'; import React, { useEffect, useRef } from 'react'; interface BubbleCursorProps { wrapperElement?: HTMLElement; } class Particle { lifeSpan: number; initialLifeSpan: number; velocity: { x: number; y: number }; position: { x: number; y: number }; baseDimension: number; constructor(x: number, y: number) { this.initialLifeSpan = Math.floor(Math.random() * 60 + 60); this.lifeSpan = this.initialLifeSpan; this.velocity = { x: (Math.random() < 0.5 ? -1 : 1) * (Math.random() / 10), y: -0.4 + Math.random() * -1, }; this.position = { x, y }; this.baseDimension = 4; } update(context: CanvasRenderingContext2D) { this.position.x += this.velocity.x; this.position.y += this.velocity.y; this.velocity.x += ((Math.random() < 0.5 ? -1 : 1) * 2) / 75; this.velocity.y -= Math.random() / 600; this.lifeSpan--; const scale = 0.2 + (this.initialLifeSpan - this.lifeSpan) / this.initialLifeSpan; context.fillStyle = '#e6f1f7'; context.strokeStyle = '#3a92c5'; context.beginPath(); context.arc( this.position.x - (this.baseDimension / 2) * scale, this.position.y - this.baseDimension / 2, this.baseDimension * scale, 0, 2 * Math.PI ); context.stroke(); context.fill(); context.closePath(); } } const BubbleCursor: React.FC
= ({ wrapperElement }) => { const canvasRef = useRef
(null); const particlesRef = useRef
([]); const cursorRef = useRef({ x: 0, y: 0 }); const animationFrameRef = useRef
(null); useEffect(() => { const prefersReducedMotion = window.matchMedia( '(prefers-reduced-motion: reduce)' ); let canvas: HTMLCanvasElement | null = null; let context: CanvasRenderingContext2D | null = null; let width = window.innerWidth; let height = window.innerHeight; const init = () => { if (prefersReducedMotion.matches) { console.log( 'This browser has prefers reduced motion turned on, so the cursor did not init' ); return false; } canvas = canvasRef.current; if (!canvas) return; context = canvas.getContext('2d'); if (!context) return; canvas.style.top = '0px'; canvas.style.left = '0px'; canvas.style.pointerEvents = 'none'; if (wrapperElement) { canvas.style.position = 'absolute'; wrapperElement.appendChild(canvas); canvas.width = wrapperElement.clientWidth; canvas.height = wrapperElement.clientHeight; } else { canvas.style.position = 'fixed'; document.body.appendChild(canvas); canvas.width = width; canvas.height = height; } bindEvents(); loop(); }; const bindEvents = () => { const element = wrapperElement || document.body; element.addEventListener('mousemove', onMouseMove); element.addEventListener('touchmove', onTouchMove, { passive: true }); element.addEventListener('touchstart', onTouchMove, { passive: true }); window.addEventListener('resize', onWindowResize); }; const onWindowResize = () => { width = window.innerWidth; height = window.innerHeight; if (!canvasRef.current) return; if (wrapperElement) { canvasRef.current.width = wrapperElement.clientWidth; canvasRef.current.height = wrapperElement.clientHeight; } else { canvasRef.current.width = width; canvasRef.current.height = height; } }; const onTouchMove = (e: TouchEvent) => { if (e.touches.length > 0) { for (let i = 0; i < e.touches.length; i++) { addParticle(e.touches[i].clientX, e.touches[i].clientY); } } }; const onMouseMove = (e: MouseEvent) => { if (wrapperElement) { const boundingRect = wrapperElement.getBoundingClientRect(); cursorRef.current.x = e.clientX - boundingRect.left; cursorRef.current.y = e.clientY - boundingRect.top; } else { cursorRef.current.x = e.clientX; cursorRef.current.y = e.clientY; } addParticle(cursorRef.current.x, cursorRef.current.y); }; const addParticle = (x: number, y: number) => { particlesRef.current.push(new Particle(x, y)); }; const updateParticles = () => { if (!canvas || !context) return; if (particlesRef.current.length === 0) { return; } context.clearRect(0, 0, canvas.width, canvas.height); // Update for (let i = 0; i < particlesRef.current.length; i++) { particlesRef.current[i].update(context); } // Remove dead particles for (let i = particlesRef.current.length - 1; i >= 0; i--) { if (particlesRef.current[i].lifeSpan < 0) { particlesRef.current.splice(i, 1); } } if (particlesRef.current.length === 0) { context.clearRect(0, 0, canvas.width, canvas.height); } }; const loop = () => { updateParticles(); animationFrameRef.current = requestAnimationFrame(loop); }; init(); return () => { if (canvas) { canvas.remove(); } if (animationFrameRef.current) { cancelAnimationFrame(animationFrameRef.current); } const element = wrapperElement || document.body; element.removeEventListener('mousemove', onMouseMove); element.removeEventListener('touchmove', onTouchMove); element.removeEventListener('touchstart', onTouchMove); window.removeEventListener('resize', onWindowResize); }; }, [wrapperElement]); return
; }; export default BubbleCursor;