fix(editor): fix zoom and disableScrollLimit -> enableScrollLimit (#390)

* fix(core): flow-nodes-content-layer auto resize

* fix(editor): fix zoom and disableScrollLimit -> enableScrollLimit
This commit is contained in:
xiamidaxia 2025-06-18 21:58:07 +08:00 committed by GitHub
parent 7c376e3254
commit d21cdae3ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 74 additions and 50 deletions

View File

@ -6,7 +6,7 @@ import { Divider, Dropdown } from '@douyinfe/semi-ui';
import { SelectZoom } from './styles';
export const ZoomSelect = () => {
const tools = usePlaygroundTools();
const tools = usePlaygroundTools({ maxZoom: 2, minZoom: 0.25 });
const [dropDownVisible, openDropDown] = useState(false);
return (
<Dropdown

View File

@ -184,6 +184,13 @@ export function useEditorProps(
onBind: ({ bind }) => {
bind(CustomService).toSelf().inSingletonScope();
},
scroll: {
/**
*
* Limit scrolling so that none of the nodes can see it
*/
enableScrollLimit: true,
},
/**
* Playground init
*/

View File

@ -6,7 +6,7 @@ import { Divider, Dropdown } from '@douyinfe/semi-ui';
import { SelectZoom } from './styles';
export const ZoomSelect = () => {
const tools = usePlaygroundTools();
const tools = usePlaygroundTools({ maxZoom: 2, minZoom: 0.25 });
const playground = usePlayground();
const [dropDownVisible, openDropDown] = useState(false);
return (

View File

@ -1,6 +1,6 @@
import { nanoid } from 'nanoid';
import { Field, FieldArray } from '@flowgram.ai/free-layout-editor';
import { ConditionRow, ConditionRowValueType, VariableSelector } from '@flowgram.ai/form-materials';
import { ConditionRow, ConditionRowValueType } from '@flowgram.ai/form-materials';
import { Button } from '@douyinfe/semi-ui';
import { IconPlus, IconCrossCircleStroked } from '@douyinfe/semi-icons';

View File

@ -101,7 +101,7 @@ export class PlaygroundConfigEntity extends ConfigEntity<PlaygroundConfigEntityD
originY: 0,
width: 0,
height: 0,
minZoom: 0.1,
minZoom: 0.25,
maxZoom: 2,
zoom: 1,
clientX: 0,

View File

@ -6,8 +6,6 @@ import {
FlowNodesTransformLayer,
type FlowRendererContribution,
type FlowRendererRegistry,
FlowScrollBarLayer,
FlowScrollLimitLayer,
} from '@flowgram.ai/renderer';
import {
type FlowDocument,
@ -94,9 +92,7 @@ export class FlowRegisters
FlowNodesContentLayer, // 节点内容渲染
FlowLinesLayer, // 线条渲染
FlowLabelsLayer, // Label 渲染
PlaygroundLayer, // 画布基础层,提供缩放、手势等能力
FlowScrollLimitLayer, // 控制滚动范围
FlowScrollBarLayer // 滚动条
PlaygroundLayer // 画布基础层,提供缩放、手势等能力
);
}

View File

@ -81,7 +81,7 @@ export class FlowNodesContentLayer extends Layer {
const PortalRenderer = this.getPortalRenderer(data!);
function Portal(): JSX.Element {
React.useLayoutEffect(() => {
React.useEffect(() => {
// 第一次加载需要把宽高通知
if (!entity.getNodeMeta().autoResizeDisable && node.clientWidth && node.clientHeight) {
const transform = entity.getData<FlowNodeTransformData>(FlowNodeTransformData);

View File

@ -87,7 +87,7 @@ export interface EditorProps<
reduxDevTool?: ReduxDevToolPluginOptions;
scroll?: {
disableScrollLimit?: boolean; // 关闭滚动限制
enableScrollLimit?: boolean; // 开启滚动限制
disableScrollBar?: boolean; // 关闭滚动条
};

View File

@ -72,7 +72,7 @@ export interface PlaygroundTools {
}
export function usePlaygroundTools(props?: PlaygroundToolsPropsType): PlaygroundTools {
const { maxZoom = 2, minZoom = 0.25, padding = 30 } = props || {};
const { maxZoom, minZoom, padding = 30 } = props || {};
const playground = usePlayground();
const container = usePlaygroundContainer();
const historyService = container.isBound(HistoryService)
@ -85,12 +85,6 @@ export function usePlaygroundTools(props?: PlaygroundToolsPropsType): Playground
const [canUndo, setCanUndo] = useState(false);
const [canRedo, setCanRedo] = useState(false);
const fitViewOptions = {
maxZoom,
minZoom,
padding,
};
const changeLayout = useCallback(
(newLayout?: FlowLayoutDefault) => {
const allNodes = doc.getAllNodes();
@ -105,8 +99,10 @@ export function usePlaygroundTools(props?: PlaygroundToolsPropsType): Playground
});
setTimeout(() => {
fitView(doc, playground.config, {
...fitViewOptions,
easingDuration: 300,
padding,
maxZoom: playground.config.config.maxZoom,
minZoom: playground.config.config.minZoom,
});
}, 10);
setTimeout(() => {
@ -118,14 +114,11 @@ export function usePlaygroundTools(props?: PlaygroundToolsPropsType): Playground
doc.setLayout(newLayout);
updateLayout(doc.layout);
},
[doc, playground]
[doc, playground, padding]
);
const handleZoomOut = useCallback(
(easing?: boolean) => {
if (zoom < minZoom) {
return;
}
playground?.config.zoomout(easing);
},
[zoom, playground]
@ -133,9 +126,6 @@ export function usePlaygroundTools(props?: PlaygroundToolsPropsType): Playground
const handleZoomIn = useCallback(
(easing?: boolean) => {
if (zoom > maxZoom) {
return;
}
playground?.config.zoomin(easing);
},
[zoom, playground]
@ -145,12 +135,14 @@ export function usePlaygroundTools(props?: PlaygroundToolsPropsType): Playground
const handleFitView = useCallback(
(easing?: boolean, easingDuration?: number) => {
fitView(doc, playground.config, {
...fitViewOptions,
easing,
easingDuration,
padding,
maxZoom: playground.config.config.maxZoom,
minZoom: playground.config.config.minZoom,
});
},
[doc, playground]
[doc, playground, padding]
);
const handleUpdateZoom = useCallback(
@ -179,6 +171,14 @@ export function usePlaygroundTools(props?: PlaygroundToolsPropsType): Playground
return () => dispose.dispose();
}, [playground, historyService]);
useEffect(() => {
const config = playground.config.config;
playground.config.updateConfig({
maxZoom: maxZoom !== undefined ? maxZoom : config.maxZoom,
minZoom: minZoom !== undefined ? minZoom : config.minZoom,
});
}, [playground, maxZoom, minZoom]);
return {
zoomin: handleZoomIn,
zoomout: handleZoomOut,

View File

@ -141,7 +141,7 @@ export function createFixedLayoutPreset(
FlowNodesContentLayer, // 节点内容渲染
FlowNodesTransformLayer // 节点位置偏移计算
);
if (!opts.scroll?.disableScrollLimit) {
if (opts.scroll?.enableScrollLimit) {
// 控制滚动范围
ctx.playground.registerLayer(FlowScrollLimitLayer);
}

View File

@ -41,5 +41,10 @@ export namespace FixedLayoutProps {
/**
*
*/
export const DEFAULT: FixedLayoutProps = EditorProps.DEFAULT as FixedLayoutProps;
export const DEFAULT: FixedLayoutProps = {
...EditorProps.DEFAULT,
scroll: {
enableScrollLimit: true,
},
} as FixedLayoutProps;
}

View File

@ -44,7 +44,19 @@ export interface PlaygroundTools {
setMouseScrollDelta: (mouseScrollDelta: number | ((zoom: number) => number)) => void;
}
export function usePlaygroundTools(): PlaygroundTools {
export interface PlaygroundToolsPropsType {
/**
* 2
*/
maxZoom?: number;
/**
* 0.25
*/
minZoom?: number;
}
export function usePlaygroundTools(props?: PlaygroundToolsPropsType): PlaygroundTools {
const { maxZoom, minZoom } = props || {};
const playground = usePlayground();
const doc = useService<WorkflowDocument>(WorkflowDocument);
@ -55,9 +67,6 @@ export function usePlaygroundTools(): PlaygroundTools {
const handleZoomOut = useCallback(
(easing?: boolean) => {
if (zoom < 0.1) {
return;
}
playground?.config.zoomout(easing);
},
[zoom, playground]
@ -65,9 +74,6 @@ export function usePlaygroundTools(): PlaygroundTools {
const handleZoomIn = useCallback(
(easing?: boolean) => {
if (zoom > 1.9) {
return;
}
playground?.config.zoomin(easing);
},
[zoom, playground]
@ -171,6 +177,14 @@ export function usePlaygroundTools(): PlaygroundTools {
});
}
useEffect(() => {
const config = playground.config.config;
playground.config.updateConfig({
maxZoom: maxZoom !== undefined ? maxZoom : config.maxZoom,
minZoom: minZoom !== undefined ? minZoom : config.minZoom,
});
}, [playground, maxZoom, minZoom]);
return {
zoomin: handleZoomIn,
zoomout: handleZoomOut,

View File

@ -181,7 +181,7 @@ export function createFreeLayoutPreset(
}
},
});
if (!opts.scroll?.disableScrollLimit) {
if (opts.scroll?.enableScrollLimit) {
// 控制滚动范围
ctx.playground.registerLayer(FlowScrollLimitLayer);
}

View File

@ -1,5 +1,6 @@
import { useCallback, useEffect, useState } from 'react';
import { DisposableCollection } from '@flowgram.ai/utils';
import {
EditorState,
EditorStateConfigEntity,
@ -7,7 +8,6 @@ import {
useConfigEntity,
usePlayground,
} from '@flowgram.ai/core';
import { DisposableCollection } from '@flowgram.ai/utils';
export interface PlaygroundToolsPropsType {
/**
@ -49,7 +49,7 @@ export interface PlaygroundTools {
}
export function usePlaygroundTools(props?: PlaygroundToolsPropsType): PlaygroundTools {
const { maxZoom = 2, minZoom = 0.25 } = props || {};
const { maxZoom, minZoom } = props || {};
const playground = usePlayground();
const editorState = useConfigEntity(EditorStateConfigEntity, true);
@ -57,29 +57,23 @@ export function usePlaygroundTools(props?: PlaygroundToolsPropsType): Playground
const handleZoomOut = useCallback(
(easing?: boolean) => {
if (zoom < minZoom) {
return;
}
playground.config.zoomout(easing);
},
[zoom, playground, minZoom],
[playground]
);
const handleZoomIn = useCallback(
(easing?: boolean) => {
if (zoom > maxZoom) {
return;
}
playground.config.zoomin(easing);
},
[zoom, playground, maxZoom],
[playground]
);
const handleUpdateZoom = useCallback(
(value: number, easing?: boolean, easingDuration?: number) => {
playground.config.updateZoom(value, easing, easingDuration);
},
[playground],
[playground]
);
const handleToggleIneractiveType = useCallback(() => {
@ -92,10 +86,18 @@ export function usePlaygroundTools(props?: PlaygroundToolsPropsType): Playground
useEffect(() => {
const dispose = new DisposableCollection();
dispose.push(playground.onZoom(z => setZoom(z)));
dispose.push(playground.onZoom((z) => setZoom(z)));
return () => dispose.dispose();
}, [playground]);
useEffect(() => {
const config = playground.config.config;
playground.config.updateConfig({
maxZoom: maxZoom !== undefined ? maxZoom : config.maxZoom,
minZoom: minZoom !== undefined ? minZoom : config.minZoom,
});
}, [playground, maxZoom, minZoom]);
return {
zoomin: handleZoomIn,
zoomout: handleZoomOut,