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

In the g6 mind diagram layout, I want to realize the drag node crying to change the order of the node, so I want to insert a temporary node to show the current insertion position, and when the collision node is detected during the dragging process, and then the method of inserting the node is called, the page will be stuck, and the temporary node will be inserted into the diagram after being released #6535

Open
wangtao-bugkiller opened this issue Nov 18, 2024 · 0 comments

Comments

@wangtao-bugkiller
Copy link

Describe the bug / 问题描述

g6脑图布局里面想要实现拖拽节点哭改变节点的顺序,所以就想着去插入一个临时节点来显示当前插入的位置,在拖拽的过程的时候检测到碰撞节点然后调用插入节点的方法页面就会卡住,无法继续拖拽,放开后临时节点插入到了图中

Reproduction link / 重现链接

No response

Steps to Reproduce the Bug or Issue / 重现步骤

image

G6 Version / G6 版本

4.x

Operating System / 操作系统

macOS

Browser / 浏览器

Chrome

Additional context / 补充说明

`let dragNodeOriPos,
minDisNode,
minDisNodeId,
dragRect,
insertPos,
insertIndex,
lastInsertPostion,
lastMinDisNode,
lastMinDisNodeId,
targetIndex,
newParentId,
newParentNode,
targetInsertIndex,
targetParentID;

/**

  • 检查拖动的节点与其他节点是否发生碰撞
  • @param {Object} node - 被检查的节点对象
  • @param {Object} rect - 拖动矩形的属性,包含x、y、width、height
  • @param {number} x - 拖动矩形的x坐标
  • @param {number} y - 拖动矩形的y坐标
  • @returns {boolean|Object} - 如果没有碰撞返回false,如果发生碰撞返回包含插入位置和碰撞状态的对象
    */
    const collide = (node, rect, x, y) => {
    // 如果节点不存在,直接返回false
    if (!node) return false;
// 获取节点的边界框,并添加padding以扩大碰撞检测范围
var nodeBBox = node.getBBox(),
  padding = 10,
  expandedNodeBBox = {
    x: nodeBBox.minX - padding,
    y: nodeBBox.minY - padding,
    width: nodeBBox.width + 2 * padding,
    height: nodeBBox.height + 2 * padding,
  },
  // 构造拖动矩形的边界框,高度翻倍以适应特定的碰撞检测需求
  draggedRect = {
    x: rect.x - padding,
    y: rect.y - padding,
    width: rect.width + 2 * padding,
    height: 2 * rect.height,
  };

// 判断拖动过程中是否与其他结点发生碰撞
var isColliding =
  expandedNodeBBox.x < draggedRect.x + draggedRect.width &&
  expandedNodeBBox.x + expandedNodeBBox.width > draggedRect.x &&
  expandedNodeBBox.y < draggedRect.y + draggedRect.height &&
  expandedNodeBBox.y + expandedNodeBBox.height > draggedRect.y;

// 如果发生碰撞,根据拖动位置确定插入位置
if (isColliding) {
  var insertPosition =
    x > nodeBBox.maxX
      ? 'right'
      : x < nodeBBox.maxX && x > nodeBBox.minX
      ? y > nodeBBox.centerY
        ? 'bottom'
        : 'top'
      : 'left';
  // 返回插入位置和碰撞状态
  return { insertPos: insertPosition, collide: true };
}

// 如果没有碰撞,返回false
return false;

};

/**

  • 遍历节点函数
  • 该函数用于在思维导图中找到并返回一个指定的节点及其索引位置
  • @param {Object} item - 需要查找的节点项,必须包含getID方法以获取节点ID
  • @param {Function} callback - 回调函数,未在本代码段中使用,但可能为未来扩展预留
  • @returns {Object} 返回一个对象,包含新父节点和目标索引
    */
    const traversNodes = (item, callback) => {
    // 初始化新节点和新索引变量
    let newNode,
    newIndex = 0;
// 获取需要查找的节点的ID
const id = item.getID();

// 使用G6工具类的树遍历方法,从保存的思维导图树结构中从上至下查找节点
G6.Util.traverseTreeUp(mindMapTree.save(), function(node, parent, index) {
  // 当找到节点ID匹配的节点时,保存该节点及其索引,并停止继续遍历
  if (node.id === id) {
    newNode = node;
    newIndex = index;
    return false;
  } else {
    // 如果当前节点不匹配,继续遍历下一个节点
    return true;
  }
});

// 返回结果对象,包含找到的节点和其索引位置
return {
  newParentNode: newNode,
  targetIndex: newIndex,
};

};

const traversRootNodes = e => {
var found = false,
nodeId = e.getID();
// 遍历树的根节点以判断是否为根节点
G6.Util.traverseTree(mindMapTree.save(), function(node, isRoot) {
if (!isRoot || node.id !== nodeId) {
found = true;
return false;
}
});
return found;
};

const registerBehavior = () => {
G6.registerBehavior('dice-mindmap-drag', {
getEvents() {
return {
'node:dragstart': 'handleItemDragStart',
'node:drag': 'handleItemDrag',
'node:dragend': 'handleItemDragEnd',
};
},

  handleItemDragStart(evt) {
    if (!isEditMode()) return;
    const { item, x, y } = evt;
    const model = item.get('model');
    if (model.id === 'RootNode') {
      return;
    }
    minDisNode = null;
    dragNodeOriPos = { x: model.x, y: model.y };
    const { minX, minY, width, height } = item.getBBox();
    dragRect = {
      deltaX: x - minX,
      deltaY: y - minY,
      width,
      height,
    };
    if (!model.collapsed && model.children && model.children.length > 0) {
      model.collapsed = true;
      mindMapTree.setItemState(item, 'collapsed', true);
      mindMapTree.refreshItem(item);
    }

    // mindMapTree.hideItem(item, false);
    // mindMapTree.refreshPositions();
  },

  /**
   * 处理思维导图节点拖拽事件
   * @param {Object} evt - 拖拽事件对象,包含拖拽的相关信息
   */
  handleItemDrag(evt) {
    // 获取当前拖拽项的模型信息
    const model = evt.item.get('model');
    if (model.id === 'RootNode') {
      return;
    }
    // 计算拖拽项的临时位置和中心点坐标
    const tempBox = {
      width: dragRect.width,
      height: dragRect.height,
      x: evt.x - dragRect.deltaX,
      y: evt.y - dragRect.deltaY,
      centerX: evt.x - dragRect.deltaX + dragRect.width / 2,
      centerY: evt.y - dragRect.deltaY + dragRect.height / 2,
    };

    // 初始化最近距离节点变量
    minDisNode = null;

    // 遍历思维导图树,检查拖拽节点与现有节点是否发生碰撞
    G6.Util.traverseTreeUp(mindMapTree.save(), function(node) {
      // 跳过当前拖拽节点和临时节点
      if (node.id === model.id || node.id === 'temp') {
        return true;
      }

      // 获取当前遍历的节点对象
      const currentNode = mindMapTree.findById(node.id);

      // 检查当前节点与拖拽节点是否发生碰撞
      const hascollided = collide(currentNode, tempBox, evt.x, evt.y);
      if (hascollided) {
        // 如果发生碰撞,更新最近距离节点及其状态
        minDisNode = currentNode;
        minDisNodeId = node.id;
        insertPos = hascollided.insertPos;
        console.log(hascollided, node.title);
        return false;
      }
    });

    // 如果找到最近距离节点,更新其子节点或调整节点位置
    if (minDisNode) {
      const minx = minDisNode.getBBox().minX;
      mindMapTree.findDataById('temp') && mindMapTree.removeChild('temp', false);
      const tempNode = {
        id: 'temp',
        type: 'dice-mind-map-temp',
        title: '',
      };

      // 根据拖拽位置更新节点或调整节点位置
      if (minx <= evt.x) {
        if (minDisNodeId === lastMinDisNodeId && lastInsertPostion === insertPos) {
          return;
        }

        mindMapTree.findDataById('temp') && mindMapTree.removeChild('temp', false);

        const targetNode = mindMapTree.findDataById(minDisNodeId) || { children: [] };
        const tagerChild = cloneDeep(targetNode.children || []);
        tagerChild.push(tempNode);
        targetParentID = minDisNode.getID();

        if (minDisNode.getModel().collapsed) {
          minDisNode.getModel().collapsed = false;
        }

        targetInsertIndex = tagerChild.length - 1;
        console.log(targetNode.children,tagerChild, 'c',targetInsertIndex);
        mindMapTree.updateChildren(tagerChild, minDisNodeId);
      } else {
        if (minDisNodeId === lastMinDisNodeId && lastInsertPostion === insertPos) {
          return;
        }

        const traversedNodes = traversNodes(minDisNode);
        newParentNode = traversedNodes.newParentNode;
        targetIndex = traversedNodes.targetIndex;
        newParentId = newParentNode?.id;
        if (!newParentId) {
          return;
        }

        mindMapTree.findDataById('temp') && mindMapTree.removeChild('temp', false);

        const childrenArray = cloneDeep(newParentNode.children || []);
        insertIndex = insertPos === 'top' ? targetIndex : targetIndex + 1;
        childrenArray.splice(insertIndex, 0, tempNode);
        console.log(childrenArray, 'p',insertIndex);
        mindMapTree.updateChildren(childrenArray, newParentId);
        targetParentID = newParentId;
        targetInsertIndex = insertIndex;
      }

      // 更新拖拽项的位置
      evt.item.updatePosition({
        x: dragRect.deltaX,
        y: dragRect.deltaY,
      });

      // 更新最近距离节点及其插入位置的缓存
      lastMinDisNodeId = minDisNodeId;
      lastInsertPostion = insertPos;
    }
  },
  handleItemDragEnd(evt) {},
});

};`

@github-actions github-actions bot changed the title g6脑图布局里面想要实现拖拽节点哭改变节点的顺序,所以就想着去插入一个临时节点来显示当前插入的位置,在拖拽的过程的时候检测到碰撞节点然后调用插入节点的方法页面就会卡住,无法继续拖拽,放开后临时节点插入到了图中 In the g6 mind diagram layout, I want to realize the drag node crying to change the order of the node, so I want to insert a temporary node to show the current insertion position, and when the collision node is detected during the dragging process, and then the method of inserting the node is called, the page will be stuck, and the temporary node will be inserted into the diagram after being released Nov 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant