G6 icon indicating copy to clipboard operation
G6 copied to clipboard

Combos - `layoutcfg.preventComboOverlap` does not prevent overlapping combos

Open cliffordfajardo opened this issue 2 years ago • 2 comments

Describe the bug

preventComboOverlap:true inside of G6's layout config does not prevent combos from overlapping when combos are opened near each other.

Your Example Website or App

https://codesandbox.io/s/g6-4-6-3--preventcombooverlap--bug-ovlu74?file=/index.js

Steps to Reproduce the Bug or Issue

  1. A user loads a graph with multiple combos on the graph, which all start with collapsed: true and has preventComboOverlap: true (docs) enabled in their layout config.

  2. A user double clicks a combo to open it

Expected behavior

As user when I enable preventComboOverlap:true in my g6 layout config:

  • [ ] it should prevent combos from overlapping with each other
  • [ ] it should not drastically change the size of a combo (as seen in video --- maybe this can be converted to new issue)
  • [ ] it should work with any combo layout type ('comboForce', 'graph', 'grid', ..) and also work when the user doesn't specify one in the layout (it defaults to some layout?)
  • [ ] it should consider to the current view to when expanding or collapsing, that is try to keep keep the positions as much as possible (see dropdown details below)
  • [ ] it should keep combo in view after expansion, instead of moving it completely off the screen; non technical users will get confused by this behavior. Instead of completely moving it out of view, it should keep the continuity of the the current view. Related: https://github.com/antvis/G6/issues/3551

Codesandbox demo (code from video below): https://codesandbox.io/s/g6-4-6-3--preventcombooverlap--bug-ovlu74?file=/index.js

https://user-images.githubusercontent.com/6743796/158892336-b218a665-6f20-47da-9ba3-1a3c61d9b714.mp4

Expected Behavior Concepts (these are not from G6)

Example 1️⃣ : Ideal Circular Combo Expansion/Contraction Concept

This shows a combo being expanded; after combo expansion, the current combo pushes the other combos around it, while still keeping as much of the content in view.

https://user-images.githubusercontent.com/6743796/158896506-3aa145c0-bb32-493a-9459-affd7210ebf1.mp4

This is the hyperlink in the video "automatic graph layouts": https://cambridge-intelligence.com/layouts/

Similar to example above, but this one shows what happens when the combo is collapsed. It looks like they remembering the last position is useful for collapse/expand 00-keylines-regraph-combo-expand-collapse-example

Example 2️⃣ : Rectangular Combo Expansion/Contraction Concept

This shows a rectangular combo being expanded; after combo expansion, the current combo pushes the other combos around it, while still keeping as much of the content in view.

https://user-images.githubusercontent.com/6743796/158895334-afb26005-c22a-449d-899c-8786b2c582d6.mp4

This is the hyperlink referenced in the video: "sequential layouts": https://cambridge-intelligence.com/sequential-layout-the-best-way-to-handle-tiered-data/

Example 3️⃣ : From Circular to Rectangular Combo (show space utilization transition)

https://user-images.githubusercontent.com/6743796/158895919-9c3c2076-6ac3-4b02-8de1-c54ccb9b91e6.mp4

Platform

  • OS: MacOS, all browsers,
  • G6 version 4.6.3

Related

  • https://github.com/antvis/G6/issues/3551
  • https://github.com/antvis/G6/issues/3524

cliffordfajardo avatar Mar 18 '22 00:03 cliffordfajardo

try this configuration: https://codesandbox.io/s/g6-4-6-3--preventcombooverlap--bug-forked-dv0dqk

for the rect one, I tried to implement it in this demo: https://codesandbox.io/s/wandering-snowflake-24tr6r?file=/index.js Still some works to do, e.g. better animation, considering collapsed combo edge in layout, and so on

Yanyan-Wang avatar May 05 '22 15:05 Yanyan-Wang

Hello,

I have a similar issue as well. I have multiple combo's, nested in each other but the items all seem to overlap. Any ideas what could be causing this or how I can fix this?

import React, { useEffect, useState,useRef } from 'react';
// import  data  from '../data/data';
import G6 from '@antv/g6';
import { NodeTooltips, EdgeToolTips, NodeContextMenu } from '../components'
import './registerShape';

const data = {
    nodes: [
        {
            id: 'node1',
            img: 'http://localhost:3000/awsIcons/ec2-a1.svg',
            type: 'image',
            size: 50,
            label: '1-2412352345235',
            comboId: 'subnet-01f03ebc7dbe73f8b',
        },
        {
            id: 'node2',
            img: 'http://localhost:3000/awsIcons/ec2-a1.svg',
            type: 'image',
            size: 50,
            label: '1-2412352345235',
            comboId: 'subnet-0b5eea98975d61ff7',
        },
        {
            id: 'node3',
            img: 'http://localhost:3000/awsIcons/ec2-a1.svg',
            type: 'image',
            size: 50,
            label: '1-2412352345235',
            comboId: 'subnet-0b5eea98975d61ff7',
        },
        {
            id: 'node4',
            img: 'http://localhost:3000/awsIcons/ec2-a1.svg',
            type: 'image',
            size: 50,
            label: '1-2412352345235',
            comboId: 'subnet-04e452be6984d535b',
        },
        {
            id: 'node5',
            img: 'http://localhost:3000/awsIcons/ec2-a1.svg',
            type: 'image',
            size: 50,
            label: '1-2412352345235',
            comboId: 'subnet-04e452be6984d535b',
        },
        {
            id: 'node6',
            img: 'http://localhost:3000/awsIcons/ec2-a1.svg',
            type: 'image',
            size: 50,
            label: '1-2412352345235',
            comboId: 'subnet-04e452be6984d535b',
        },
        {
            id: 'node7',
            img: 'http://localhost:3000/awsIcons/ec2-a1.svg',
            type: 'image',
            size: 50,
            label: '1-2412352345235',
            comboId: 'subnet-04e452be6984d535b',
        },
    ],
    combos: [
        {
            id: 'eu-west-1',
            label: 'us-east-1',
            size: 80,
        },
        {
            parentId: "eu-west-1",
            id: 'vpc-05c1cd7b63042cee5',
            label: 'vpc-05c1cd7b63042cee5',

        },
        {
            parentId: "vpc-05c1cd7b63042cee5",
            id: "subnet-01f03ebc7dbe73f8b",
            label: "subnet-01f03ebc7dbe73f8b",
            size: 180
        },
        {
            parentId: "vpc-05c1cd7b63042cee5",
            id: "subnet-04e452be6984d535b",
            label: "subnet-04e452be6984d535b",
            size: 180
        },
        {
            parentId: "vpc-05c1cd7b63042cee5",
            id: "subnet-0b5eea98975d61ff7",
            label: "subnet-0b5eea98975d61ff7",
            size: 180
            
        },
        // {
        //     parentId: "vpc-05c1cd7b63042cee5",
        //     id: "subnet-0f2320f37c3ed41a7",
        //     label: "subnet-0f2320f37c3ed41a7"
        // }
    ],
};
const playground = () => {
    const ref = useRef(null);
    let graph = null;

    useEffect(()=>{
        if(!graph){
            graph = new G6.Graph({
                  container: ref.current,
                  width: 1800,
                  height: 1000,
                  // translate the graph to align the canvas's center, support by v3.5.1
                  fitCenter: true,
                  // Set groupByTypes to false to get rendering result with reasonable visual zIndex for combos
                  groupByTypes: false,
                  modes: {
                      default: ['drag-canvas', 'drag-node', 'drag-combo', 'collapse-expand-combo'],
                  },
                  layout: {
                    type: 'grid',
                    begin: [0, 0],
                    preventOverlap: true, // nodeSize or size in data is required for preventOverlap: true
                    preventOverlapPdding: 20,
                    condense: false,
                    // rows: 5,
                    // cols: 5,
                    // sortBy: 'degree',
                  },
                  defaultCombo: {
                      type: 'rect',
                      /* The minimum size of the combo. combo 最小大小 */
                      size: [50, 50],
                      /* style for the keyShape */
                      style: {
                        lineWidth: 1,
                      },
                      labelCfg: {
                          /* label's offset to the keyShape */
                          // refY: 10,
                          /* label's position, options: center, top, bottom, left, right */
                          position: 'top',
                          /* label's style */
                        //   style: {
                        //     fontSize: 18,
                        //     paddingLeft: '0px'
                        //   },
                      },
                  },
                  /* styles for different states, there are built-in styles for states: active, inactive, selected, highlight, disable */
                  /* you can extend it or override it as you want */
                  // comboStateStyles: {
                  //   active: {
                  //     fill: '#f00',
                  //     opacity: 0.5
                  //   },
                  // },
              });
          
              graph.data(data);
              graph.render();
          
              graph.on('combo:mouseenter', (evt) => {
                  const { item } = evt;
                  graph.setItemState(item, 'active', true);
              });
          
              graph.on('combo:mouseleave', (evt) => {
                  const { item } = evt;
                  graph.setItemState(item, 'active', false);
              });
              graph.on('combo:click', (evt) => {
                  const { item } = evt;
                  graph.setItemState(item, 'selected', true);
              });
              graph.on('canvas:click', (evt) => {
                  graph.getCombos().forEach((combo) => {
                      graph.clearItemStates(combo);
                  });
              });

        }
    },[])
    return (
        <div ref={ref}>
        </div>
    )
}

export default playground

image

The behavior i was looking for was more in line with this: image

Many thanks!!

jhylton avatar May 07 '22 18:05 jhylton

const data = {
    nodes: [
        {
            id: 'node1',
            img: 'http://localhost:3000/awsIcons/ec2-a1.svg',
            type: 'image',
            size: 50,
            label: '1-2412352345235',
            comboId: 'subnet-01f03ebc7dbe73f8b',
        },
        {
            id: 'node2',
            img: 'http://localhost:3000/awsIcons/ec2-a1.svg',
            type: 'image',
            size: 50,
            label: '1-2412352345235',
            comboId: 'subnet-0b5eea98975d61ff7',
        },
        {
            id: 'node3',
            img: 'http://localhost:3000/awsIcons/ec2-a1.svg',
            type: 'image',
            size: 50,
            label: '1-2412352345235',
            comboId: 'subnet-0b5eea98975d61ff7',
        },
        {
            id: 'node4',
            img: 'http://localhost:3000/awsIcons/ec2-a1.svg',
            type: 'image',
            size: 50,
            label: '1-2412352345235',
            comboId: 'subnet-04e452be6984d535b',
        },
        {
            id: 'node5',
            img: 'http://localhost:3000/awsIcons/ec2-a1.svg',
            type: 'image',
            size: 50,
            label: '1-2412352345235',
            comboId: 'subnet-04e452be6984d535b',
        },
        {
            id: 'node6',
            img: 'http://localhost:3000/awsIcons/ec2-a1.svg',
            type: 'image',
            size: 50,
            label: '1-2412352345235',
            comboId: 'subnet-04e452be6984d535b',
        },
        {
            id: 'node7',
            img: 'http://localhost:3000/awsIcons/ec2-a1.svg',
            type: 'image',
            size: 50,
            label: '1-2412352345235',
            comboId: 'subnet-04e452be6984d535b',
        },
    ],
    combos: [
        {
            id: 'eu-west-1',
            label: 'us-east-1',
            size: 80,
        },
        {
            parentId: "eu-west-1",
            id: 'vpc-05c1cd7b63042cee5',
            label: 'vpc-05c1cd7b63042cee5',

        },
        {
            parentId: "vpc-05c1cd7b63042cee5",
            id: "subnet-01f03ebc7dbe73f8b",
            label: "subnet-01f03ebc7dbe73f8b",
            size: 180
        },
        {
            parentId: "vpc-05c1cd7b63042cee5",
            id: "subnet-04e452be6984d535b",
            label: "subnet-04e452be6984d535b",
            size: 180
        },
        {
            parentId: "vpc-05c1cd7b63042cee5",
            id: "subnet-0b5eea98975d61ff7",
            label: "subnet-0b5eea98975d61ff7",
            size: 180
            
        },
        // {
        //     parentId: "vpc-05c1cd7b63042cee5",
        //     id: "subnet-0f2320f37c3ed41a7",
        //     label: "subnet-0f2320f37c3ed41a7"
        // }
    ],
};

Hi, we provide 'comboCombined' layout for graph with combos, and I tried your data in this demo, looks good now: https://codesandbox.io/s/g6-4-6-3--preventcombooverlap--bug-forked-tcrhtk?file=/index.js image

Please upgrade your @antv/g6 and @antv/layout to latest version to get these features. P.S. since the imgs in your image nodes are not available, I just replace them into rects in the demo.

Yanyan-Wang avatar Dec 14 '22 13:12 Yanyan-Wang

Hey, has there been any update on this? I still have the the issue where when I expand nested combos, in causes overlap despite setting preventOverlap to true

ephraimrothschild avatar Mar 24 '23 13:03 ephraimrothschild

@Yanyan-Wang Hello there! is there any update on this issue? I have encountered almost exactly the same issue, where expanding/collapsing combo is causing the nested combo to overlap...

In the example codesandbox you posted, if double-clicking on any combo to expand/collapse, you will see this overlap issue. https://codesandbox.io/s/g6-4-6-3--preventcombooverlap--bug-forked-tcrhtk?file=/index.js

ravengao avatar Jun 28 '23 03:06 ravengao

It seems that this issue can't be solved. Does anyone have a workaround for that?

ahules avatar Nov 15 '23 12:11 ahules