UNPKG

vue-rewards

Version:

Vue-rewards lets you add micro-interactions to your app, and rewards users with the rain of confetti, emoji or balloons in seconds.

107 lines (96 loc) 2.62 kB
import { EmojiConfig } from './Emoji.types'; import { animate, generatePhysics, getRandomInt, } from '../../functions/helpers'; import { Particle } from '../../Main.types'; const defaultEmoji = ['🤓', '😊', '🥳']; const factors = [-0.6, -0.3, 0, 0.3, 0.6]; const createElements = ( root: Element, elementCount: number, elementSize: number, zIndex: number, position: string, emojis: string[] ) => Array.from({ length: elementCount }).map((_, index) => { const element = document.createElement('span'); element.innerHTML = emojis[index % emojis.length]; element.style.fontSize = `${elementSize + getRandomInt(0, 4)}px`; element.style.position = position; element.style.zIndex = `${zIndex}`; root.appendChild(element); return { element, differentiator: getRandomInt(0, factors.length) }; }); const updateParticle = ( particle: Particle, progress: number, decay: number ) => { const { x, y, tiltAngle, angle2D, velocity, differentiator, wobble } = particle.physics; particle.physics.x += Math.cos(angle2D) * velocity; particle.physics.y += Math.sin(angle2D) * velocity; particle.physics.wobble += 0; particle.physics.velocity *= decay; particle.physics.y += 5; particle.physics.tiltAngle += 0.05; const wobbleX = x + (factors[differentiator] * progress * wobble * wobble + 20 * Math.sin(wobble / 4)); particle.element.style.transform = `translate3d(${wobbleX}px, ${y}px, 0) rotate3d(0, 0, 1, ${ differentiator % 2 ? tiltAngle : -1 * tiltAngle }rad)`; if (progress > 0.5) { particle.element.style.opacity = `${2 - 2 * progress}`; } }; export const emoji = ( root: Element, internalAnimatingCallback: () => void, config?: EmojiConfig ) => { const options = config || {}; const { elementCount = 20, elementSize = 25, emoji: emojiArray = defaultEmoji, angle = 90, spread = 45, decay = 0.94, lifetime = 200, startVelocity = 35, zIndex = 0, position = 'fixed', onAnimationComplete, } = options; const spanElements = createElements( root, elementCount, elementSize, zIndex, position, emojiArray ); const particles = spanElements.map(({ element, differentiator }) => ({ element, physics: generatePhysics(angle, spread, startVelocity, differentiator), })); const onFinish = () => { if (typeof onAnimationComplete === 'function') { onAnimationComplete(); } internalAnimatingCallback(); }; animate({ root, particles, decay, lifetime, updateParticle, onFinish, }); };