antvis/G6

在多层combo结构的图里,自定义layout无法获取正确的combo size #4729

ravengao posted onGitHub

问题描述

您好~我想实现一个自定义layout:根据用户与combo的交互(expand/collapse)动态获取所有combo的状态、位置与size,然后在自定义layout的execute()layout(data)计算并设置combo的 [x, y]。但我在计算combo位置时发现self.nodes.size并非combo实际渲染的宽高,导致自定义layout下combo的位置与预期不符。

自定义layout原本预期: 所有最外层的combo里,先检查每个combo是否collapsed——

  1. collapsed combo先横向排布
  2. expanded combo均向右平移nodeWidth / 2,所有combo应该向左对齐
  3. 每次用户expand/collapse combo,触发当前layout重新计算

然而渲染出的结果并不符合预期,而且有overlap,证明execute()获取的self.nodes.size并不准确。 如果双击collapse一个最外层combo,会发现self.nodes.size并不是collapsed后的size(即使combo.collapsed=true)

我的问题是:该如何获取combo最新的正确size?尤其是在用户expand/collapse combo之后

非常感谢!:)

codesandbox示例的layout config如下:

    layout: {
      type: "comboCombined",
      innerLayout: new G6.Layout.grid({}),
      outerLayout: new G6.Layout["custom-layout"]({})
    }

自定义layout代码如下:

    G6.registerLayout("custom-layout", {
      execute() {
        const self = this;
        const { nodes } = self;

        const collapsedCombos = [];
        const expandedCombos = [];

        nodes.forEach((node) => {
          const { itemType, collapsed } = node;

          if (itemType === "combo" && !collapsed) {
            expandedCombos.push(node);
          } else {
            collapsedCombos.push(node);
          }
        });

        // 1. position collapsed combos first, top aligned
        collapsedCombos.forEach((combo, i) => {
          let comboW = combo.size[0];

          combo.x = comboW / 2 + i * comboW;
          combo.y = -200;
        });

        // 2. position expanded combos, left aligned
        let prevHeight = 0;
        expandedCombos.forEach((combo, i) => {
          let comboW = combo.size[0];
          let comboH = combo.size[1];

          combo.x = comboW / 2;
          combo.y = prevHeight + comboH / 2;

          prevHeight += comboH;
        });
      }
    });

重现链接

https://codesandbox.io/s/sample-map-mngv57?file=/src/CloudMapConfig.ts

重现步骤

  1. 初始化graph,自定义layout渲染的结果并不符合预期
  2. 或者双击collapse一个最外层combo,layout并未根据combo最新的状态(expand/collapse)更新

预期行为

在执行自定义layout计算combo位置时,每次都能获取combo最新的正确size(width与height)

平台

  • 操作系统: [macOS, React 18]
  • 网页浏览器: [Google Chrome]
  • G6 版本: [4.8.17]

屏幕截图或视频(可选)

初始状态 <img width="709" alt="Screen Shot 2023-07-11 at 12 59 35 PM" src="https://github.com/antvis/G6/assets/7640361/940b4b9a-5cab-425e-8966-d8bf5ad19223">

有collapsed combo的情况 <img width="695" alt="Screen Shot 2023-07-11 at 12 56 30 PM" src="https://github.com/antvis/G6/assets/7640361/f66abcfd-39c6-463c-aec7-bff7bcd3c57c">

补充说明(可选)

No response


outerLayout 里面 nodes 的 size 应该是最紧包裹内部子元素的一个最小包围盒,计算位置的时候可能需要额外考虑一下 combo 渲染 padding,比如配置 comboCombined 布局参数:comboPadding: 40

posted by Yanyan-Wang almost 2 years ago

@Yanyan-Wang

outerLayout 里面 nodes 的 size 应该是最紧包裹内部子元素的一个最小包围盒,计算位置的时候可能需要额外考虑一下 combo 渲染 padding,比如配置 comboCombined 布局参数:comboPadding: 40

谢谢!我看了一下comboCombined布局的源码,发现comboPadding在计算时是恒定数字(e.g. 20)。但如果combo的padding是一个不统一的array(e.g. [100, 20, 20, 20]),矩形combo size实际渲染出来的结果会和预期有差异。

顺便捉一个comboCombined布局的bug(一个corner case) 这里的源码是:只要nodes不存在或者只有一个,不执行接下来的combo布局计算。有些情况下,self.nodes.length <= 1,但是graph里其实还存在闭合combos(collapsed=true)所以nodes在数据里看起来不存在。一旦满足这种情况,comboCombined就会跳过collapsed combos不执行任何布局计算。

    ComboCombinedLayout.prototype.execute = function () {
        var self = this;
        var nodes = self.nodes;
        var center = self.center;

        // execute layout algorithm even there are no nodes (there can be collapsed combos)
        // 把下面这段源码注释后,上面的corner case就会work as expected
        // if (!nodes || nodes.length === 0) {
        //     if (self.onLayoutEnd)
        //         self.onLayoutEnd();
        //     return;
        // }
        // if (nodes.length === 1) {
        //     nodes[0].x = center[0];
        //     nodes[0].y = center[1];
        //     if (self.onLayoutEnd)
        //         self.onLayoutEnd();
        //     return;
        // }
        self.initVals();
        // layout
        self.run();
        if (self.onLayoutEnd)
            self.onLayoutEnd();
    };

不过这些问题我靠改源码然后patch-package解决了,如果有需要我可以开一个PR :)

posted by ravengao over 1 year ago

This issue has been closed because it has been outdate for a long time. Please open a new issue if you still need help.

这个 issue 已经被关闭,因为 它已经过期很久了。 如果你仍然需要帮助,请创建一个新的 issue。

posted by github-actions[bot] 10 months ago

Fund this Issue

$0.00
Funded

Pull requests