import React from 'react'; import styled from '@emotion/styled'; import { keyframes } from "@emotion/react"; const PERCEPTIBLE = 1 / 60; export interface ReelProps { duration: number; width: number; frameWidth: number; stamps: number[]; children?: React.ReactNode; } export const Reel: React.FunctionComponent = (props) => { if (props.duration === 0) { return ( {props.children} ); } const factor = Math.pow(10, magnitude(PERCEPTIBLE / (props.duration / 100)) + 1); const p = (s: number): number => Math.round((s / (props.duration / 100)) * factor) / factor; const animation = keyframes` ${props.stamps.map((stamp, i) => ` ${p(stamp)}% { transform: translateX(-${props.frameWidth * i}px); } `).join('\n')} `; return ( {props.children} ); } function magnitude(x: number): number { const y = Math.abs(x); if (y > 1) { return 0; } const result = Math.floor(Math.log(y) / Math.log(10) + 1); return result === 0 ? result : -1 * result; } export interface StyledAnimationStageProps { animation: ReturnType; duration: number; } const StyledAnimationStage = styled.g` animation-name: ${(props) => props.animation}; animation-duration: ${(props) => props.duration}s; animation-iteration-count: infinite; animation-timing-function: steps(1, end); `;