import React, { useMemo, useRef } from 'react' import useMeasure from 'react-use-measure' import { mergeRefs, useDrag } from 'leva/plugin' import { useRange, useInvertedRange } from './bezier-utils' import { Svg } from './StyledBezier' import type { Bezier as BezierType, BezierProps } from './bezier-types' const HANDLE_RADIUS = 4 interface LineProps { sx: number sy: number cx: number cy: number } function Line({ sx, sy, cx, cy }: LineProps) { const a = Math.atan2(cy - sy, cx - sx) const cxs = cx - HANDLE_RADIUS * Math.cos(a) const cys = cy - HANDLE_RADIUS * Math.sin(a) return } export function BezierSvg({ displayValue, onUpdate, withPreview, }: Pick & { withPreview: boolean }) { const r = useRange() const ir = useInvertedRange() const [ref, { width, height }] = useMeasure() const svgRef = useRef(null) const handleLeft = useRef(null) const handleRight = useRef(null) const bounds = useRef() const bind = useDrag(({ xy: [x, y], event, first, memo }) => { if (first) { bounds.current = svgRef.current!.getBoundingClientRect() memo = [handleLeft.current, handleRight.current].indexOf(event!.target as any) if (memo < 0) memo = x - bounds.current.left < width / 2 ? 0 : 1 memo *= 2 } const relX = x - bounds.current!.left const relY = y - bounds.current!.top onUpdate((v: BezierType) => { const newV = [...v] newV[memo] = ir(relX, width) newV[memo + 1] = 1 - ir(relY, height) return newV }) return memo }) const { x1, y1, x2, y2 } = displayValue const { sx, sy, ex, ey, cx1, cy1, cx2, cy2 } = useMemo( () => ({ sx: r(0, width), sy: r(1, height), ex: r(1, width), ey: r(0, height), cx1: r(x1, width), cy1: r(1 - y1, height), cx2: r(x2, width), cy2: r(1 - y2, height), }), [r, x1, y1, x2, y2, width, height] ) return ( ) }