Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(extension): 【dynamic-group】修复mousemove和isCollapsed相关问题 #1919

Merged
merged 8 commits into from
Oct 29, 2024

Conversation

wbccb
Copy link
Contributor

@wbccb wbccb commented Oct 17, 2024

fix #1912
fix #1914
fix #1918

#1912

问题发生的原因

下面视频展示的关系为:dynamicGroupA嵌套dynamicGroupB,dynamicGroupB嵌套普通Node

由于dynamicGroupA嵌套dynamicGroupB,在dynamicGroupA进行折叠时,会触发dynamicGroupB的隐藏,从而触发dynamicGroupB的componentWillUnmount()销毁,但是如下面视频所示,dynamicGroupB的componentDidMount()注册了很多事件:

  componentDidMount() {
    super.componentDidMount()
    const { eventCenter } = this.props.graphModel
    // 在 group 旋转时,对组内的所有子节点也进行对应的旋转计算
    eventCenter.on('node:rotate', this.onNodeRotate)
    // 在 group 缩放时,对组内的所有子节点也进行对应的缩放计算
    eventCenter.on('node:resize', this.onNodeResize)
    // 在 group 移动时,对组内的所有子节点也进行对应的移动计算
    eventCenter.on('node:mousemove', this.onNodeMouseMove)
  }

但是忘记执行对应的事件移除,因此导致每一次折叠=>展开的时候,都会重复注册一次事件,因此导致下面视频所展示触发多次 moveNodes,也就是dynamicGroupB移动1px,会触发多次它的children的1px移动,从而造成移动错乱问题

on-off.mp4

解决方法

将componentDidMount注册的监听事件方法抽离出来,为后面解除事件监听做准备

提交记录:refactor(extension): 【dynamic-group】将componentDidMount注册的监听事件方法抽离出来,为后面解除事件监听做准备

交互逻辑无变化,只是将注册方法抽离为this.xxxx方法,放在外部

componentWillUnmount移除监听

  componentWillUnmount() {
    super.componentWillUnmount()
    const { eventCenter } = this.props.graphModel
    eventCenter.off('node:rotate', this.onNodeRotate)
    eventCenter.off('node:resize', this.onNodeResize)
    eventCenter.off('node:mousemove', this.onNodeMouseMove)
  }

#1914

问题发生的原因

#1858改变了 group移动时,移动时需要同时移动组内的所有节点的逻辑代码,原来2.0.8版本中的逻辑是:

graphModel.addNodeMoveRules((model, deltaX, deltaY) => {
    // 判断如果是 group,移动时需要同时移动组内的所有节点
    if (model.isGroup) {
      const nodeIds = this.getNodesInGroup(model as DynamicGroupNodeModel)
      graphModel.moveNodes(nodeIds, deltaX, deltaY, true)
      return true
    }
    //...
}

2.0.9版本中的逻辑是
2 0 9

而为什么会出现问题呢?

是因为

  • onDragging()->会进行坐标的处理,其中包括了SCALE的转化->触发addNodeMoveRules的注册的监听方法,也就是上面的2.0.8版本中的逻辑的graphModel.moveNodes(),此时的deltaXdeltaY是经过SCALE后的数据
  • 而在在2.0.9版本中的mousemove回调是跟 onDragging()同时发生的,拿到的deltaXdeltaY是没有经过SCALE后的数据
handleMouseMove = (e: MouseEvent) => {
    //...
    Promise.resolve().then(() => {
    this.onDragging({
        deltaX,
        deltaY,
        event: e,
    })
    this.eventCenter?.emit(EventType[`${this.eventType}_MOUSEMOVE`], {
        deltaX,
        deltaY,
        e,
        data: this.data || elementData,
    })
    //...
}

解决方法

deltaXdeltaY增加SCALE的转化

#1918

问题发生的原因

packages/extension/src/dynamic-group/model.ts中有这么一段代码

setAttributes() {
    super.setAttributes()

    // 初始化时,如果 this.isCollapsed 为 true,则主动触发一次折叠操作
    if (this.isCollapsed) {
       this.toggleCollapse(true)
    }
}

初始化时主动触发一次折叠操作是没问题的,但是我们从toggleCollapse可以知道,我们是通过elementsModelMap去获取对应的数据,但是存在着group已经初始化完成,但是children还没初始化的情况,这个时候elementsModelMap是找不到children数据的

toggleCollapse(collapse?: boolean) {
    const nextCollapseState = !!collapse
    this.isCollapsed = nextCollapseState
    // step 1
    //...

    // step 2
    const childrenArr = Array.from(this.children)

    forEach(childrenArr, (elementId) => {
      // FIX: 当使用 graphModel.getElement 获取元素时,会因为
      // const model = this.graphModel.getElement(elementId)
      const model = this.graphModel.elementsModelMap.get(elementId)
      //...
    })
    // step 3
    //...
  }

group已经初始化完成,但是children还没初始化的情况是如何发生的呢?

lf.render({
  nodes: [
    {
      type: "dynamic-group",
      x: 400,
      y: 400,
      properties: {
        children: ["rect_2"],
        isCollapsed: true,
      },
    },
    {
      id: "rect_2",
      type: "circle",
      x: 400,
      y: 400,
    },
  ],
});

当我们使用上面的数据进行渲染时,会触发getModelAfterSnapToGrid(),然后触发groupnew Model(),从而触发model.setAttributes()->toggleCollapse()->使用elementsModelMap寻找对应的childrenId对应的Model,此时找不到childrenModel,因为要等待group初始化好了,再执行childrennew Model(),然后将childrenModel放入到elementsModelMap

getModelAfterSnapToGrid(node: NodeConfig) {
    //...
    const nodeModel = new Model(node, this)
    this.nodeModelMap.set(nodeModel.id, nodeModel)
    this.elementsModelMap.set(nodeModel.id, nodeModel)

    return nodeModel
}

因此只要把数据翻转,也就是下面的顺序,先渲染children->group,那么一切就正常了!

lf.render({
  nodes: [
    {
      id: "rect_2",
      type: "circle",
      x: 400,
      y: 400,
    },
    {
      type: "dynamic-group",
      x: 400,
      y: 400,
      properties: {
        children: ["rect_2"],
        isCollapsed: true,
      },
    },
  ],
});

解决方法

将初始化时主动触发一次折叠操作放在全部渲染完成之后再执行,也就是
1918

Copy link

changeset-bot bot commented Oct 17, 2024

⚠️ No Changeset found

Latest commit: 05c801c

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@wbccb wbccb changed the title fix(extension): 【dynamic-group】componentWillUnmount移除事件监听,解决折叠再展开的子元素移动错乱问题 fix(extension): 【dynamic-group】修复mousemove和isCollapsed相关问题 Oct 19, 2024
@boyongjiong
Copy link
Collaborator

大佬也太效率了。

还有点小问题,我这边把 dynamicGroup example 中 group_1 的 isCollapsed 设置为 true,初始化之后,分组没有自动合起来 0.o,你看下你那边有没有这个问题?
image

@wbccb
Copy link
Contributor Author

wbccb commented Oct 29, 2024

oh...失误=_=刚刚提交的@wbccbchore(extension): 【dynamic-group】删除无用的注释代码

image

又引发另一个eslint报错,我修复下

@wbccb
Copy link
Contributor Author

wbccb commented Oct 29, 2024

image
"我这边把 dynamicGroup example 中 group_1 的 isCollapsed 设置为 true,初始化之后,分组没有自动合起来"是因为上面截图的原因 @boyongjiong 例子可能得优化下,用的还是旧的Group

需要我把这个代码也提交上去吗?

@boyongjiong
Copy link
Collaborator

image "我这边把 dynamicGroup example 中 group_1 的 isCollapsed 设置为 true,初始化之后,分组没有自动合起来"是因为上面截图的原因 @boyongjiong 例子可能得优化下,用的还是旧的Group

需要我把这个代码也提交上去吗?

哈哈哈,有点好笑了,我之前开发 dynamic-group 用的是 engine-browser-examples 这个项目,然后代码没有同步过来。。

没事,你不管了,我把这个 PR 过了,我去同步代码

@boyongjiong boyongjiong merged commit 740d5a0 into didi:master Oct 29, 2024
@wbccb wbccb deleted the fix/group-collapse branch October 29, 2024 08:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants