Przeglądaj źródła

fix(core): playground auto resize when openning by Modal or Tabs or js animation (#800)

* fix(resize): playground autoresize when openning by Modal or tabs or js animation

fix(core): playground autoResize when openning by Modal or tabs or js animation

* fix(core): add disposed to ResizePolling

* feat(core): playground add onResize
xiamidaxia 4 miesięcy temu
rodzic
commit
4bee877850

+ 44 - 0
packages/canvas-engine/core/src/core/utils/resize-polling.ts

@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
+ * SPDX-License-Identifier: MIT
+ */
+
+import { Disposable } from '@flowgram.ai/utils';
+
+const POLLING_MAX_TIME = 5000;
+const POLLING_INTERVAL = 100;
+
+/**
+ * ResizeObserver 在有动画情况不准确,需要轮循兜底执行 resize 几秒
+ */
+export class ResizePolling implements Disposable {
+  private _intervalKey?: number;
+
+  private _disposed = false;
+
+  private _startTime = 0;
+
+  start(fn: () => boolean) {
+    if (this._intervalKey !== undefined) {
+      clearInterval(this._intervalKey);
+    }
+    if (this._disposed) {
+      return;
+    }
+    this._startTime = Date.now();
+    this._intervalKey = window.setInterval(() => {
+      const success = fn();
+      if (!success || Date.now() - this._startTime >= POLLING_MAX_TIME) {
+        clearInterval(this._intervalKey);
+      }
+    }, POLLING_INTERVAL);
+  }
+
+  dispose() {
+    if (this._intervalKey !== undefined) {
+      clearInterval(this._intervalKey);
+    }
+    this._disposed = true;
+    this._intervalKey = undefined;
+  }
+}

+ 39 - 11
packages/canvas-engine/core/src/playground.ts

@@ -6,7 +6,6 @@
 import React from 'react';
 
 import { nanoid } from 'nanoid';
-import { debounce } from 'lodash-es';
 import { inject, injectable, optional, named } from 'inversify';
 import {
   Disposable,
@@ -20,6 +19,7 @@ import { CommandService } from '@flowgram.ai/command';
 import { SelectionService } from './services';
 import { PlaygroundContribution, PlaygroundRegistry } from './playground-contribution';
 import { PlaygroundConfig } from './playground-config';
+import { ResizePolling } from './core/utils/resize-polling';
 import {
   type PipelineDimension,
   // PipelineDispatcher,
@@ -65,9 +65,15 @@ export class Playground<CONTEXT = PlaygroundContext> implements Disposable {
 
   readonly onScroll: Event<{ scrollX: number; scrollY: number }>;
 
+  get onResize() {
+    return this.pipelineRegistry.onResizeEmitter.event;
+  }
+
   // 唯一 className,适配画布多实例场景
   private playgroundClassName = nanoid();
 
+  private _resizePolling = new ResizePolling();
+
   static getLatest(): Playground | undefined {
     const instances = Playground.getAllInstances();
     return instances[instances.length - 1];
@@ -133,6 +139,7 @@ export class Playground<CONTEXT = PlaygroundContext> implements Disposable {
       // this.ableManager,
       this.commandService,
       this.selectionService,
+      this._resizePolling,
       Disposable.create(() => {
         playgroundInstances.delete(this);
         this.node.remove();
@@ -273,12 +280,17 @@ export class Playground<CONTEXT = PlaygroundContext> implements Disposable {
     if (this.isReady) return;
     this.isReady = true;
     if (this.playgroundConfig.autoResize) {
-      const resize = debounce(() => {
+      const resize = () => {
         if (this.disposed) return;
         this.resize();
-      }, 0);
+      };
+      const resizeWithPolling = () => {
+        if (this.disposed) return;
+        this.resize();
+        this._resizePolling.start(() => this.resize());
+      };
       if (typeof ResizeObserver !== 'undefined') {
-        const resizeObserver = new ResizeObserver(resize);
+        const resizeObserver = new ResizeObserver(resizeWithPolling);
         resizeObserver.observe(this.node);
         this.toDispose.push(
           Disposable.create(() => {
@@ -287,9 +299,14 @@ export class Playground<CONTEXT = PlaygroundContext> implements Disposable {
         );
       } else {
         this.toDispose.push(
-          domUtils.addStandardDisposableListener(window.document.body, 'resize', resize, {
-            passive: true,
-          })
+          domUtils.addStandardDisposableListener(
+            window.document.body,
+            'resize',
+            resizeWithPolling,
+            {
+              passive: true,
+            }
+          )
         );
       }
       this.toDispose.push(
@@ -323,7 +340,7 @@ export class Playground<CONTEXT = PlaygroundContext> implements Disposable {
    * 这里会由 widget 透传进来
    * @param msg
    */
-  resize(msg?: PipelineDimension, scrollToCenter = true): void {
+  resize(msg?: PipelineDimension, scrollToCenter = true): boolean {
     if (!msg) {
       const boundingRect = this.node.getBoundingClientRect();
       msg = {
@@ -336,8 +353,9 @@ export class Playground<CONTEXT = PlaygroundContext> implements Disposable {
     // 页面宽度变更 触发滚动偏移
     const { width, height } = this.config.config;
     if (msg.width === 0 || msg.height === 0) {
-      return;
+      return false;
     }
+    const oldConfig = this.config.config;
     let { scrollX, scrollY } = this.config.config;
     // 这个在处理滚动
     if (scrollToCenter && width && Math.round(msg.width) !== width) {
@@ -346,8 +364,18 @@ export class Playground<CONTEXT = PlaygroundContext> implements Disposable {
     if (scrollToCenter && height && Math.round(msg.height) !== height) {
       scrollY += (height - msg.height) / 2;
     }
-    this.config.updateConfig({ ...msg, scrollX, scrollY });
-    this.pipelineRegistry.onResizeEmitter.fire(msg);
+    if (
+      oldConfig.clientY !== msg.clientY ||
+      oldConfig.clientX !== msg.clientX ||
+      Math.round(msg.width) !== width ||
+      Math.round(msg.height) !== height ||
+      oldConfig.scrollX !== scrollX ||
+      oldConfig.scrollY !== scrollY
+    ) {
+      this.config.updateConfig({ ...msg, scrollX, scrollY });
+      this.pipelineRegistry.onResizeEmitter.fire(msg);
+    }
+    return true;
   }
 
   /**

+ 0 - 2
packages/materials/form-materials/src/components/variable-selector/index.tsx

@@ -73,8 +73,6 @@ export const VariableSelector = ({
     return icon;
   };
 
-  console.log('debugger treeValue', treeValue);
-
   return (
     <>
       <UITreeSelect