/
F1lya
/
Modal_Window
Обзор
Документация
Войти
/
F1lya
/
Modal_Window
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
useFrameEditor.ts
191 строка
6 KB
F1lya
upload files
20 окт 2025, 14:17
20 окт 2025, 14:17
f9aac0b
Код
Авторство
О чём код?
import { useState, useCallback, useRef } from 'react'; import { Frame, Position, ContainerSize, EditorState, CropSettings } from '../types'; const DEFAULT_CROP_SETTINGS: CropSettings = { maintainAspectRatio: true, aspectRatio: 1, minFrameSize: 50 }; export const useFrameEditor = (containerSize: ContainerSize, cropSettings: CropSettings = DEFAULT_CROP_SETTINGS) => { const [editorState, setEditorState] = useState<EditorState>({ frame: { x: 0, y: 0, width: 0, height: 0 }, isDragging: false, isResizing: false, resizeCorner: null }); const dragStartRef = useRef<Position>({ x: 0, y: 0 }); const frameStartRef = useRef<Frame>({ x: 0, y: 0, width: 0, height: 0 }); const initializeFrame = useCallback((imageAspectRatio: number) => { const { width: containerWidth, height: containerHeight } = containerSize; const frameSize = Math.min(containerWidth, containerHeight) * 0.6; const aspectRatio = cropSettings.maintainAspectRatio ? cropSettings.aspectRatio : imageAspectRatio; const frameWidth = frameSize; const frameHeight = frameSize / aspectRatio; const x = (containerWidth - frameWidth) / 2; const y = (containerHeight - frameHeight) / 2; setEditorState(prev => ({ ...prev, frame: { x: Math.max(0, x), y: Math.max(0, y), width: Math.min(frameWidth, containerWidth), height: Math.min(frameHeight, containerHeight) } })); }, [containerSize, cropSettings]); const startDrag = useCallback((e: React.MouseEvent, currentFrame: Frame) => { dragStartRef.current = { x: e.clientX, y: e.clientY }; frameStartRef.current = { ...currentFrame }; setEditorState(prev => ({ ...prev, isDragging: true })); }, []); const startResize = useCallback((e: React.MouseEvent, corner: string, currentFrame: Frame) => { dragStartRef.current = { x: e.clientX, y: e.clientY }; frameStartRef.current = { ...currentFrame }; setEditorState(prev => ({ ...prev, isResizing: true, resizeCorner: corner })); }, []); const dragFrame = useCallback((e: MouseEvent) => { const deltaX = e.clientX - dragStartRef.current.x; const deltaY = e.clientY - dragStartRef.current.y; const newX = Math.max(0, Math.min( frameStartRef.current.x + deltaX, containerSize.width - frameStartRef.current.width )); const newY = Math.max(0, Math.min( frameStartRef.current.y + deltaY, containerSize.height - frameStartRef.current.height )); setEditorState(prev => ({ ...prev, frame: { ...prev.frame, x: newX, y: newY } })); }, [containerSize]); const resizeFrame = useCallback((e: MouseEvent) => { const deltaX = e.clientX - dragStartRef.current.x; const deltaY = e.clientY - dragStartRef.current.y; let newFrame = { ...frameStartRef.current }; const currentAspectRatio = frameStartRef.current.width / frameStartRef.current.height; const aspectRatio = cropSettings.maintainAspectRatio ? cropSettings.aspectRatio : currentAspectRatio; switch (editorState.resizeCorner) { case 'se': newFrame.width = Math.max( cropSettings.minFrameSize, Math.min( frameStartRef.current.width + deltaX, containerSize.width - frameStartRef.current.x ) ); newFrame.height = cropSettings.maintainAspectRatio ? newFrame.width / aspectRatio : newFrame.height; break; case 'sw': newFrame.width = Math.max( cropSettings.minFrameSize, Math.min( frameStartRef.current.width - deltaX, frameStartRef.current.x + frameStartRef.current.width ) ); newFrame.height = cropSettings.maintainAspectRatio ? newFrame.width / aspectRatio : newFrame.height; newFrame.x = frameStartRef.current.x + (frameStartRef.current.width - newFrame.width); break; case 'ne': newFrame.height = Math.max( cropSettings.minFrameSize, Math.min( frameStartRef.current.height - deltaY, frameStartRef.current.y + frameStartRef.current.height ) ); newFrame.width = cropSettings.maintainAspectRatio ? newFrame.height * aspectRatio : newFrame.width; newFrame.y = frameStartRef.current.y + (frameStartRef.current.height - newFrame.height); break; case 'nw': newFrame.width = Math.max( cropSettings.minFrameSize, Math.min( frameStartRef.current.width - deltaX, frameStartRef.current.x + frameStartRef.current.width ) ); newFrame.height = cropSettings.maintainAspectRatio ? newFrame.width / aspectRatio : newFrame.height; newFrame.x = frameStartRef.current.x + (frameStartRef.current.width - newFrame.width); newFrame.y = frameStartRef.current.y + (frameStartRef.current.height - newFrame.height); break; } // Boundary checks newFrame.x = Math.max(0, Math.min(newFrame.x, containerSize.width - newFrame.width)); newFrame.y = Math.max(0, Math.min(newFrame.y, containerSize.height - newFrame.height)); newFrame.width = Math.min(newFrame.width, containerSize.width - newFrame.x); newFrame.height = Math.min(newFrame.height, containerSize.height - newFrame.y); setEditorState(prev => ({ ...prev, frame: newFrame })); }, [containerSize, cropSettings, editorState.resizeCorner]); const stopInteraction = useCallback(() => { setEditorState(prev => ({ ...prev, isDragging: false, isResizing: false, resizeCorner: null })); }, []); const setFrame = useCallback((frame: Frame) => { setEditorState(prev => ({ ...prev, frame })); }, []); const resetFrame = useCallback((imageAspectRatio: number) => { initializeFrame(imageAspectRatio); }, [initializeFrame]); return { editorState, initializeFrame, startDrag, startResize, dragFrame, resizeFrame, stopInteraction, setFrame, resetFrame }; };