import React, { FC, useCallback, useEffect, useMemo, useReducer } from 'react'; import { useRef } from 'react'; import { ApplicationLayout } from '../../layouts/ApplicationLayout'; import { ResponsiveSVG, Group, Line } from '@cutting/svg'; import { useParentSize } from '@cutting/use-get-parent-size'; import { AxisBottom, AxisLeft } from '@visx/axis'; import { LinePath } from '@visx/shape'; import { curveMonotoneX } from '@visx/curve'; import { SVGMathJax } from '@cutting/use-mathjax'; import * as styles from './Sine.css'; import { getScales, reducer, initialState, xTickValues, PiMap, PiMapKeys } from './utils'; import { BottomAxis } from './BottomAxis'; const Sine: FC = () => { const containerRef = useRef(null); const { width, height } = useParentSize(containerRef); const tickFrame = useRef(); const { initialX, initialY, firstX, radius, xAxisScale, yAxisScale } = useMemo( () => getScales({ width, height }), [width, height], ); const [state, dispatch] = useReducer(reducer, initialState); const animate = useCallback( (time: number) => dispatch({ type: 'TICK', payload: { radius, firstX, time, xAxisScale } }), [firstX, radius, xAxisScale], ); useEffect(() => { tickFrame.current = requestAnimationFrame(animate.bind(state.time)); return () => { if (!tickFrame.current) { return; } cancelAnimationFrame(tickFrame.current); }; }, [animate, firstX, radius, state.time]); const expanded = width > 1 && height > 1; return (
{state.rays.map(({ cosX, sinY, label, offsetX, offsetY }) => ( ))} {expanded && ( <> `$${PiMap[x as unknown as PiMapKeys]}$`} axisClassName={styles.axis} axisLineClassName={styles.axisLine} tickStroke="#fff" tickComponent={BottomAxis} /> className={styles.sine} x={(d) => xAxisScale(d.x) ?? 0} y={(d) => yAxisScale(d.y) ?? 0} strokeWidth={1} curve={curveMonotoneX} data={state.sine} /> )}
); }; export default Sine;