|
|
@@ -47,6 +47,8 @@ export const ImageBlock: React.FC<ImageBlockProps> = ({
|
|
47
|
47
|
mouseX: 0,
|
|
48
|
48
|
mouseY: 0,
|
|
49
|
49
|
});
|
|
|
50
|
+ const pendingResizeEventRef = useRef<MouseEvent | null>(null);
|
|
|
51
|
+ const resizeFrameRef = useRef<number | null>(null);
|
|
50
|
52
|
|
|
51
|
53
|
// 查找当前块的位置
|
|
52
|
54
|
const isFirst = index === 0;
|
|
|
@@ -159,22 +161,19 @@ export const ImageBlock: React.FC<ImageBlockProps> = ({
|
|
159
|
161
|
setIsResizing(true);
|
|
160
|
162
|
}, []);
|
|
161
|
163
|
|
|
162
|
|
- // 拖拽调整中
|
|
163
|
|
- const handleResizeMove = useCallback((e: MouseEvent) => {
|
|
164
|
|
- if (!isResizing) return;
|
|
165
|
|
-
|
|
166
|
|
- const deltaX = e.clientX - startSizeRef.current.mouseX;
|
|
167
|
|
-
|
|
|
164
|
+ const applyResizeEvent = useCallback((event: MouseEvent) => {
|
|
|
165
|
+ const deltaX = event.clientX - startSizeRef.current.mouseX;
|
|
|
166
|
+
|
|
168
|
167
|
// 计算新宽度(保持宽高比)
|
|
169
|
168
|
const newWidth = Math.max(50, startSizeRef.current.width + deltaX);
|
|
170
|
169
|
const aspectRatio = startSizeRef.current.height / startSizeRef.current.width;
|
|
171
|
170
|
const newHeight = newWidth * aspectRatio;
|
|
172
|
|
-
|
|
|
171
|
+
|
|
173
|
172
|
// 转换为当前单位
|
|
174
|
173
|
const { unit } = block.style;
|
|
175
|
174
|
const unitMap = { cm: 37.795, inch: 96, px: 1 };
|
|
176
|
175
|
const multiplier = unitMap[unit] || 1;
|
|
177
|
|
-
|
|
|
176
|
+
|
|
178
|
177
|
updateBlock(block.id, {
|
|
179
|
178
|
style: {
|
|
180
|
179
|
...block.style,
|
|
|
@@ -182,12 +181,37 @@ export const ImageBlock: React.FC<ImageBlockProps> = ({
|
|
182
|
181
|
height: parseFloat((newHeight / multiplier).toFixed(2)),
|
|
183
|
182
|
},
|
|
184
|
183
|
});
|
|
185
|
|
- }, [isResizing, block.id, block.style, updateBlock]);
|
|
|
184
|
+ }, [block.id, block.style, updateBlock]);
|
|
|
185
|
+
|
|
|
186
|
+ // 拖拽调整中
|
|
|
187
|
+ const handleResizeMove = useCallback((e: MouseEvent) => {
|
|
|
188
|
+ if (!isResizing) return;
|
|
|
189
|
+ pendingResizeEventRef.current = e;
|
|
|
190
|
+
|
|
|
191
|
+ if (resizeFrameRef.current !== null) return;
|
|
|
192
|
+
|
|
|
193
|
+ resizeFrameRef.current = requestAnimationFrame(() => {
|
|
|
194
|
+ resizeFrameRef.current = null;
|
|
|
195
|
+ const pendingEvent = pendingResizeEventRef.current;
|
|
|
196
|
+ pendingResizeEventRef.current = null;
|
|
|
197
|
+ if (!pendingEvent) return;
|
|
|
198
|
+
|
|
|
199
|
+ applyResizeEvent(pendingEvent);
|
|
|
200
|
+ });
|
|
|
201
|
+ }, [applyResizeEvent, isResizing]);
|
|
186
|
202
|
|
|
187
|
203
|
// 结束拖拽调整
|
|
188
|
204
|
const handleResizeEnd = useCallback(() => {
|
|
|
205
|
+ if (pendingResizeEventRef.current) {
|
|
|
206
|
+ applyResizeEvent(pendingResizeEventRef.current);
|
|
|
207
|
+ }
|
|
|
208
|
+ if (resizeFrameRef.current !== null) {
|
|
|
209
|
+ cancelAnimationFrame(resizeFrameRef.current);
|
|
|
210
|
+ resizeFrameRef.current = null;
|
|
|
211
|
+ }
|
|
|
212
|
+ pendingResizeEventRef.current = null;
|
|
189
|
213
|
setIsResizing(false);
|
|
190
|
|
- }, []);
|
|
|
214
|
+ }, [applyResizeEvent]);
|
|
191
|
215
|
// 监听鼠标移动和释放事件
|
|
192
|
216
|
React.useEffect(() => {
|
|
193
|
217
|
if (isResizing) {
|
|
|
@@ -199,6 +223,11 @@ export const ImageBlock: React.FC<ImageBlockProps> = ({
|
|
199
|
223
|
return () => {
|
|
200
|
224
|
document.removeEventListener('mousemove', handleResizeMove);
|
|
201
|
225
|
document.removeEventListener('mouseup', handleResizeEnd);
|
|
|
226
|
+ if (resizeFrameRef.current !== null) {
|
|
|
227
|
+ cancelAnimationFrame(resizeFrameRef.current);
|
|
|
228
|
+ resizeFrameRef.current = null;
|
|
|
229
|
+ }
|
|
|
230
|
+ pendingResizeEventRef.current = null;
|
|
202
|
231
|
document.body.style.cursor = '';
|
|
203
|
232
|
document.body.style.userSelect = '';
|
|
204
|
233
|
};
|