diff --git a/packages/sheets-drawing-ui/src/services/canvas-float-dom-manager.service.ts b/packages/sheets-drawing-ui/src/services/canvas-float-dom-manager.service.ts index 84f5c9f4fe4..044ff46cef6 100644 --- a/packages/sheets-drawing-ui/src/services/canvas-float-dom-manager.service.ts +++ b/packages/sheets-drawing-ui/src/services/canvas-float-dom-manager.service.ts @@ -14,22 +14,22 @@ * limitations under the License. */ -import type { IDisposable, IPosition, ITransformState, Nullable, Serializable, Worksheet } from '@univerjs/core'; +import type { IDisposable, IPosition, ITransformState, Nullable, Serializable, Workbook, Worksheet } from '@univerjs/core'; import type { IDrawingJsonUndo1 } from '@univerjs/drawing'; import type { BaseObject, IBoundRectNoAngle, IRectProps, IRender, Scene, SpreadsheetSkeleton } from '@univerjs/engine-render'; import type { ISetFrozenMutationParams } from '@univerjs/sheets'; import type { IFloatDomData, ISheetDrawingPosition, ISheetFloatDom } from '@univerjs/sheets-drawing'; import type { IFloatDomLayout } from '@univerjs/ui'; import type { IInsertDrawingCommandParams } from '../commands/commands/interfaces'; -import { Disposable, DisposableCollection, generateRandomId, ICommandService, Inject, IUniverInstanceService } from '@univerjs/core'; +import { Disposable, DisposableCollection, fromEventSubject, generateRandomId, ICommandService, Inject, IUniverInstanceService, UniverInstanceType } from '@univerjs/core'; import { DrawingTypeEnum, getDrawingShapeKeyByDrawingSearch, IDrawingManagerService } from '@univerjs/drawing'; import { DRAWING_OBJECT_LAYER_INDEX, IRenderManagerService, Rect, SHEET_VIEWPORT_KEY } from '@univerjs/engine-render'; import { getSheetCommandTarget, SetFrozenMutation } from '@univerjs/sheets'; import { DrawingApplyType, ISheetDrawingService, SetDrawingApplyMutation } from '@univerjs/sheets-drawing'; -import { ISheetSelectionRenderService, SetScrollOperation, SetZoomRatioOperation, SheetSkeletonManagerService } from '@univerjs/sheets-ui'; +import { ISheetSelectionRenderService, SetZoomRatioOperation, SheetSkeletonManagerService, VIEWPORT_KEY } from '@univerjs/sheets-ui'; import { CanvasFloatDomService } from '@univerjs/ui'; -import { BehaviorSubject, Subject } from 'rxjs'; +import { BehaviorSubject, filter, map, Subject, switchMap } from 'rxjs'; import { InsertSheetDrawingCommand } from '../commands/commands/insert-sheet-drawing.command'; export interface ICanvasFloatDom { @@ -371,29 +371,50 @@ export class SheetCanvasFloatDomManagerService extends Disposable { } private _scrollUpdateListener() { - this.disposeWithMe(this._commandService.onCommandExecuted((commandInfo) => { - const updateSheet = (unitId: string, subUnitId: string) => { - const renderObject = this._getSceneAndTransformerByDrawingSearch(unitId); - const map = this._ensureMap(unitId, subUnitId); - const ids = Array.from(map.keys()); - const target = getSheetCommandTarget(this._univerInstanceService, { unitId, subUnitId }); - const skeleton = this._renderManagerService.getRenderById(unitId)?.with(SheetSkeletonManagerService).getWorksheetSkeleton(subUnitId); - if (!renderObject || !target || !skeleton) { - return; + const updateSheet = (unitId: string, subUnitId: string) => { + const renderObject = this._getSceneAndTransformerByDrawingSearch(unitId); + const map = this._ensureMap(unitId, subUnitId); + const ids = Array.from(map.keys()); + const target = getSheetCommandTarget(this._univerInstanceService, { unitId, subUnitId }); + const skeleton = this._renderManagerService.getRenderById(unitId)?.with(SheetSkeletonManagerService).getWorksheetSkeleton(subUnitId); + if (!renderObject || !target || !skeleton) { + return; + } + ids.forEach((id) => { + const info = this._domLayerInfoMap.get(id); + if (info) { + const position = calcPosition(info.rect, renderObject.renderObject, skeleton.skeleton, target.worksheet); + info.position$.next(position); } - ids.forEach((id) => { - const info = this._domLayerInfoMap.get(id); - if (info) { - const position = calcPosition(info.rect, renderObject.renderObject, skeleton.skeleton, target.worksheet); - info.position$.next(position); - } - }); - }; - if (commandInfo.id === SetScrollOperation.id) { - const params = (commandInfo.params) as any; - const { unitId, sheetId } = params; - updateSheet(unitId, sheetId); - } else if (commandInfo.id === SetZoomRatioOperation.id) { + }); + }; + let time = 0; + + this.disposeWithMe( + + this._univerInstanceService.getCurrentTypeOfUnit$(UniverInstanceType.UNIVER_SHEET) + .pipe( + filter((sheet) => !!sheet), + map((sheet) => { + const render = this._renderManagerService.getRenderById(sheet.getUnitId()); + return render ? { render, unitId: sheet.getUnitId(), subUnitId: sheet.getActiveSheet().getSheetId() } : null; + }), + filter((render) => !!render), + switchMap((render) => fromEventSubject(render.render.scene.getViewport(VIEWPORT_KEY.VIEW_MAIN)!.onMouseWheel$) + .pipe( + map(() => ({ unitId: render.unitId, subUnitId: render.subUnitId })) + ) + ) + ) + .subscribe(({ unitId, subUnitId }) => { + const now = performance.now(); + time = now; + updateSheet(unitId, subUnitId); + }) + + ); + this.disposeWithMe(this._commandService.onCommandExecuted((commandInfo) => { + if (commandInfo.id === SetZoomRatioOperation.id) { const params = (commandInfo.params) as any; const { unitId } = params; const subUnitIds = Array.from(this._domLayerMap.get(unitId)?.keys() ?? []); diff --git a/packages/ui/src/views/components/dom/FloatDom.tsx b/packages/ui/src/views/components/dom/FloatDom.tsx index 848388bc9f3..920b151fb40 100644 --- a/packages/ui/src/views/components/dom/FloatDom.tsx +++ b/packages/ui/src/views/components/dom/FloatDom.tsx @@ -16,7 +16,8 @@ import type { IFloatDom } from '../../../services/dom/canvas-dom-layer.service'; import { IUniverInstanceService, UniverInstanceType, useDependency } from '@univerjs/core'; -import React, { memo } from 'react'; +import React, { memo, useEffect, useMemo, useRef } from 'react'; +import { distinctUntilChanged, first } from 'rxjs'; import { ComponentManager } from '../../../common'; import { useObservable } from '../../../components/hooks/observable'; import { CanvasFloatDomService } from '../../../services/dom/canvas-dom-layer.service'; @@ -25,55 +26,110 @@ import styles from './index.module.less'; const FloatDomSingle = memo((props: { layer: IFloatDom; id: string }) => { const { layer, id } = props; const componentManager = useDependency(ComponentManager); - const position = useObservable(layer.position$); + const size$ = useMemo(() => layer.position$.pipe( + distinctUntilChanged( + (prev, curr) => prev.absolute.left === curr.absolute.left && + prev.absolute.top === curr.absolute.top && + prev.endX - prev.startX === curr.endX - curr.startX && + prev.endY - prev.startY === curr.endY - curr.startY + ) + ), [layer.position$]); + + const position = useObservable(useMemo(() => layer.position$.pipe(first()), [layer.position$])); + const domRef = useRef(null); + const innerDomRef = useRef(null); + const transformRef = useRef(`transform: rotate(${position?.rotate}deg) translate(${position?.startX}px, ${position?.startY}px)`); + const innerStyle = useRef({ + + }); const Component = typeof layer.componentKey === 'string' ? componentManager.get(layer.componentKey) : layer.componentKey; - const layerProps: any = { + const layerProps: any = useMemo(() => ({ data: layer.data, ...layer.props, - }; + }), [layer.data, layer.props]); + + useEffect(() => { + const subscription = layer.position$.subscribe((position) => { + transformRef.current = `rotate(${position.rotate}deg) translate(${position.startX}px, ${position.startY}px)`; + if (domRef.current) { + domRef.current.style.transform = transformRef.current; + } + }); + + const sizeSubscription = size$.subscribe((size) => { + if (domRef.current) { + domRef.current.style.width = `${size.endX - size.startX}px`; + domRef.current.style.height = `${size.endY - size.startY}px`; + } + + if (innerDomRef.current) { + const style = { + width: `${size.width}px`, + height: `${size.height}px`, + left: `${size.absolute.left ? 0 : 'auto'}`, + top: `${size.absolute.top ? 0 : 'auto'}`, + right: `${size.absolute.left ? 'auto' : 0}`, + bottom: `${size.absolute.top ? 'auto' : 0}`, + }; - return position - ? ( + innerDomRef.current.style.width = style.width; + innerDomRef.current.style.height = style.height; + innerDomRef.current.style.left = style.left; + innerDomRef.current.style.top = style.top; + innerDomRef.current.style.right = style.right; + innerDomRef.current.style.bottom = style.bottom; + + innerStyle.current = style; + } + }); + return () => { + subscription.unsubscribe(); + sizeSubscription.unsubscribe(); + }; + }, [layer.position$, size$]); + + const component = useMemo(() => Component ? : null, [Component, layerProps]); + + if (!position) { + return null; + } + + return ( +
{ + layer.onPointerMove(e.nativeEvent); + }} + onPointerDown={(e) => { + layer.onPointerDown(e.nativeEvent); + }} + onPointerUp={(e) => { + layer.onPointerUp(e.nativeEvent); + }} + onWheel={(e) => { + layer.onWheel(e.nativeEvent); + }} + >
{ - layer.onPointerMove(e.nativeEvent); - }} - onPointerDown={(e) => { - layer.onPointerDown(e.nativeEvent); - }} - onPointerUp={(e) => { - layer.onPointerUp(e.nativeEvent); - }} - onWheel={(e) => { - layer.onWheel(e.nativeEvent); - }} + id={id} + ref={innerDomRef} + className={styles.floatDom} + style={{ position: 'absolute', ...innerStyle.current }} > -
- {Component ? : null} -
+ {component}
- ) - : null; +
+ ); }); export const FloatDom = ({ unitId }: { unitId?: string }) => {