import { useMemo } from 'react'; import { useCanvasStore } from '@/lib/store'; import type { PPTShapeElement } from '@/lib/types/slides'; import type { OperateResizeHandlers } from '@/lib/types/edit'; import { SHAPE_PATH_FORMULAS } from '@/configs/shapes'; import { useCommonOperate } from '../hooks/useCommonOperate'; import { RotateHandler } from './RotateHandler'; import { ResizeHandler } from './ResizeHandler'; import { BorderLine } from './BorderLine'; interface ShapeElementOperateProps { readonly elementInfo: PPTShapeElement; readonly handlerVisible: boolean; readonly rotateElement: (e: React.MouseEvent, element: PPTShapeElement) => void; readonly scaleElement: ( e: React.MouseEvent, element: PPTShapeElement, command: OperateResizeHandlers, ) => void; readonly moveShapeKeypoint: ( e: React.MouseEvent, element: PPTShapeElement, index: number, ) => void; } export function ShapeElementOperate({ elementInfo, handlerVisible, rotateElement, scaleElement, moveShapeKeypoint, }: ShapeElementOperateProps) { const canvasScale = useCanvasStore.use.canvasScale(); const scaleWidth = useMemo( () => elementInfo.width * canvasScale, [elementInfo.width, canvasScale], ); const scaleHeight = useMemo( () => elementInfo.height * canvasScale, [elementInfo.height, canvasScale], ); const { resizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight); const keypoints = useMemo(() => { if (!elementInfo.pathFormula || elementInfo.keypoints === undefined) return []; const pathFormula = SHAPE_PATH_FORMULAS[elementInfo.pathFormula]; return elementInfo.keypoints.map((keypoint, index) => { const getBaseSize = pathFormula.getBaseSize![index]; const relative = pathFormula.relative![index]; const keypointPos = getBaseSize(elementInfo.width, elementInfo.height) * keypoint; let styles: React.CSSProperties = {}; if (relative === 'left') styles = { left: keypointPos * canvasScale + 'px' }; else if (relative === 'right') styles = { left: (elementInfo.width - keypointPos) * canvasScale + 'px', }; else if (relative === 'center') styles = { left: ((elementInfo.width - keypointPos) / 2) * canvasScale + 'px', }; else if (relative === 'top') styles = { top: keypointPos * canvasScale + 'px' }; else if (relative === 'bottom') styles = { top: (elementInfo.height - keypointPos) * canvasScale + 'px', }; else if (relative === 'left_bottom') styles = { left: keypointPos * canvasScale + 'px', top: elementInfo.height * canvasScale + 'px', }; else if (relative === 'right_bottom') styles = { left: (elementInfo.width - keypointPos) * canvasScale + 'px', top: elementInfo.height * canvasScale + 'px', }; else if (relative === 'top_right') styles = { left: elementInfo.width * canvasScale + 'px', top: keypointPos * canvasScale + 'px', }; else if (relative === 'bottom_right') styles = { left: elementInfo.width * canvasScale + 'px', top: (elementInfo.height - keypointPos) * canvasScale + 'px', }; return { keypoint, styles, }; }); }, [elementInfo, canvasScale]); return (
{borderLines.map((line) => ( ))} {handlerVisible && ( <> {resizeHandlers.map((point) => ( { e.stopPropagation(); scaleElement(e, elementInfo, point.direction); }} /> ))} { e.stopPropagation(); rotateElement(e, elementInfo); }} /> {keypoints.map((keypoint, index) => (
{ e.stopPropagation(); moveShapeKeypoint(e, elementInfo, index); }} /> ))} )}
); }