import React, { useEffect, useState } from 'react'; import { StrCast } from '../../../../fields/Types'; type Props = { setFunc: (newPoints: { p1: number[]; p2: number[] }) => void; currPoints: { p1: number[]; p2: number[] }; easeFunc: string; }; const ANIMATION_DURATION = 750; // const ANIMATION_TIMING_FUNC = "cubic-bezier(.42,.97,.52,1.49)"; const ANIMATION_TIMING_FUNC = 'cubic-bezier(0.3, .2, .2, 1.4)'; const CONTAINER_WIDTH = 200; const EDITOR_WIDTH = 100; const OFFSET = (CONTAINER_WIDTH - EDITOR_WIDTH) / 2; export const TIMING_DEFAULT_MAPPINGS = { ease: 'cubic-bezier(0.25, 0.1, 0.25, 1.0)', linear: 'cubic-bezier(0.0, 0.0, 1.0, 1.0)', 'ease-in': 'cubic-bezier(0.42, 0, 1.0, 1.0)', 'ease-out': 'cubic-bezier(0, 0, 0.58, 1.0)', 'ease-in-out': 'cubic-bezier(0.42, 0, 0.58, 1.0)', }; const CubicBezierEditor = ({ setFunc, currPoints, easeFunc }: Props) => { const [animating, setAnimating] = useState(false); // Should let parent control state const [cPoints, setCPoints] = useState( currPoints ? currPoints : { p1: [0.25, 0.1], p2: [0.25, 1.0], } ); const [c1Down, setC1Down] = useState(false); const [c2Down, setC2Down] = useState(false); const roundToHundredth = (num: number) => { return Math.round(num * 100) / 100; }; const convertToPoints = (func: string) => { console.log('getting curr c points'); let strPoints = func ? func : 'ease'; if (!strPoints.startsWith('cubic')) { switch (func) { case 'linear': strPoints = 'cubic-bezier(0.0, 0.0, 1.0, 1.0)'; break; case 'ease': strPoints = 'cubic-bezier(0.25, 0.1, 0.25, 1.0)'; break; case 'ease-in': strPoints = 'cubic-bezier(0.42, 0, 1.0, 1.0)'; break; case 'ease-out': strPoints = 'cubic-bezier(0, 0, 0.58, 1.0)'; break; case 'ease-in-out': strPoints = 'cubic-bezier(0.42, 0, 0.58, 1.0)'; break; default: strPoints = 'cubic-bezier(0.25, 0.1, 0.25, 1.0)'; } } console.log('str points', strPoints); const components = strPoints .split('(')[1] .split(')')[0] .split(',') .map(elem => parseFloat(elem)); console.log('bezier components', components); return { p1: [components[0], components[1]], p2: [components[2], components[3]], }; }; useEffect(() => { if (!easeFunc.startsWith('cubic')) { setCPoints(convertToPoints(easeFunc)); } }, [easeFunc]); useEffect(() => { if (animating) { setTimeout(() => { setAnimating(false); }, ANIMATION_DURATION * 2); } }, [animating]); useEffect(() => { if (!c1Down) return; window.addEventListener('pointerup', () => { setC1Down(false); }); const handlePointerMove = (e: PointerEvent) => { const newX = cPoints.p1[0] + e.movementX / EDITOR_WIDTH; if (newX < 0 || newX > 1) { return; } setCPoints(prev => ({ ...prev, p1: [roundToHundredth(prev.p1[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(prev.p1[1] - e.movementY / EDITOR_WIDTH)], })); setFunc({ ...cPoints, p1: [roundToHundredth(cPoints.p1[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(cPoints.p1[1] - e.movementY / EDITOR_WIDTH)], }); }; window.addEventListener('pointermove', handlePointerMove); return () => window.removeEventListener('pointermove', handlePointerMove); }, [c1Down, cPoints]); useEffect(() => { if (!c2Down) return; window.addEventListener('pointerup', () => { setC2Down(false); }); const handlePointerMove = (e: PointerEvent) => { const newX = cPoints.p2[0] + e.movementX / EDITOR_WIDTH; if (newX < 0 || newX > 1) { return; } setCPoints(prev => ({ ...prev, p2: [roundToHundredth(prev.p2[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(prev.p2[1] - e.movementY / EDITOR_WIDTH)], })); setFunc({ ...cPoints, p2: [roundToHundredth(cPoints.p2[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(cPoints.p2[1] - e.movementY / EDITOR_WIDTH)], }); }; window.addEventListener('pointermove', handlePointerMove); return () => window.removeEventListener('pointermove', handlePointerMove); }, [c2Down, cPoints]); return (
{ // e.stopPropagation; // }} // onPointerMove={e => { // e.stopPropagation; // }} // onPointerUp={e => { // e.stopPropagation; // }} > {/* Outlines */} {/* Box Outline */} {/* Editor */} {/* Bottom left */} { setC1Down(true); }} onPointerUp={() => { setC1Down(false); }} x1={`${0 + OFFSET}`} y1={`${EDITOR_WIDTH + OFFSET}`} x2={`${cPoints.p1[0] * EDITOR_WIDTH + OFFSET}`} y2={`${EDITOR_WIDTH - cPoints.p1[1] * EDITOR_WIDTH + OFFSET}`} stroke="#00000000" strokeWidth="5" /> { e.stopPropagation(); setC1Down(true); }} onPointerUp={e => { setC1Down(false); }} /> {/* Top right */} { e.stopPropagation(); setC2Down(true); }} onPointerUp={e => { setC2Down(false); }} x1={`${EDITOR_WIDTH + OFFSET}`} y1={`${0 + OFFSET}`} x2={`${cPoints.p2[0] * EDITOR_WIDTH + OFFSET}`} y2={`${EDITOR_WIDTH - cPoints.p2[1] * EDITOR_WIDTH + OFFSET}`} stroke="#00000000" strokeWidth="5" /> { e.stopPropagation(); setC2Down(true); }} onPointerUp={e => { setC2Down(false); }} />
); }; export default CubicBezierEditor;