在 AntV/X6 中, 鼠标移入高亮 ,鼠标移除恢复原来样式, 并且点击后高亮,选中后线或者节点后点击键盘delete按键,可以进行删除向下的节点?

263 阅读4分钟

在 AntV/X6 中,要实现鼠标划过时高亮显示节点,并且在点击后保持高亮状态,你可以结合 cell:mouseovercell:mouseleave 和 cell:click 事件来实现。点击后保持高亮状态通常意味着你需要在节点上设置一个标志位或状态,以便在 cell:mouseleave 事件触发时能够区分是普通的鼠标离开还是已经点击过的节点。

以下是一个示例代码,展示了如何在 AntV/X6 中实现这一功能:

import { Graph } from '@antv/x6';  
  
// 初始化图形实例  
const graph = new Graph({  
  container: document.getElementById('container'),  
  width: 800,  
  height: 600,  
  grid: true,  
});  
  
// 添加一个矩形节点  
const rect = graph.addNode({  
  x: 40,  
  y: 40,  
  width: 100,  
  height: 40,  
  label: 'Hover & Click me',  
  attrs: {  
    body: {  
      fill: '#2ECC71',  
      stroke: '#000',  
      strokeWidth: 2,  
    },  
    label: {  
      text: 'Hover & Click me',  
      fill: '#fff',  
    },  
  },  
  // 添加一个自定义属性来标记节点是否被点击  
  data: {  
    isClicked: false,  
  },  
});  
  
// 定义鼠标划过时的高亮样式  
const hoverAttrs = {  
  body: {  
    fill: '#FF5733', // 更改填充颜色为橙色  
    stroke: '#000',  
    strokeWidth: 3, // 更改描边宽度  
  },  
};  
  
// 定义点击后的高亮样式(可以与 hoverAttrs 相同或不同)  
const clickedAttrs = {  
  ...hoverAttrs, // 可以复制 hoverAttrs,或者定义其他样式  
  // 如果需要,可以在这里添加或覆盖其他属性  
};  
  
// 定义 `cell:mouseover` 事件处理函数  
const handleMouseOver = (event) => {  
  const cell = event.target;  
  // 如果节点已被点击,则不应用 hover 样式(可选)  
  if (!cell.data().isClicked) {  
    cell.attr(hoverAttrs);  
  }  
};  
  
// 定义 `cell:mouseleave` 事件处理函数  
const handleMouseLeave = (event) => {  
  const cell = event.target;  
  // 如果节点未被点击,则恢复原始样式  
  if (!cell.data().isClicked) {  
    cell.resetAttrs(); // 或者使用 cell.attr(originalAttrs) 恢复之前保存的原始样式  
  }  
};  
  
// 定义 `cell:click` 事件处理函数  
const handleClick = (event) => {  
  const cell = event.target;  
  // 切换节点的点击状态  
  cell.data('isClicked', !cell.data().isClicked);  
  // 应用点击后的高亮样式  
  cell.attr(clickedAttrs);  
};  
  
// 为矩形节点添加事件监听器  
rect.on('cell:mouseover', handleMouseOver);  
rect.on('cell:mouseleave', handleMouseLeave);  
rect.on('cell:click', handleClick);

在这个示例中,我们为节点添加了一个自定义属性 data.isClicked 来标记它是否被点击过。在 cell:mouseover 和 cell:mouseleave 事件处理函数中,我们检查这个属性来决定是否应用高亮样式或恢复原始样式。在 cell:click 事件处理函数中,我们切换这个属性的值,并应用点击后的高亮样式。

请注意,这个示例中使用了 cell.resetAttrs() 方法来恢复节点的原始样式。如果你希望在点击后保留某些样式更改(比如描边宽度),你可能需要单独保存这些样式并在 cell:mouseleave 事件处理函数中进行适当的检查和应用。另外,你也可以使用其他方法来管理节点的样式状态,比如使用类名或全局状态管理。

实际工作中使用划过显示 划出消失 代码如下:

  const handleMouseenter = (event) => {
     const cell = event.cell; 
  // 如果节点已被点击,则不应用 hover 样式(可选)  
  if (!cell?.data?.isClicked) {  
   if (cell.shape == "rect") {
      //点击的是节点 ,给节点添加边框颜色和边框宽度
      emitter.emit("node-click", cell.data.zbtxZbcId);
      cell.attr("body/stroke", "#FF5733");
      cell.attr("body/stroke-width", 2);
    } else if (cell.shape == "edge") {
      //点击的是连线, ,给线添加线颜色和线宽度
      cell.attr("line/stroke", "#FF5733");
      cell.attr("line/stroke-width", 3);
    } 
  } 
    
  };
   // 定义鼠标滑入`cell:mouseenter` 事件处理函数 
  graph.on("cell:mouseenter", handleMouseenter);
  

  const handleMouseLeave = (event) => {
      const cell = event.cell;  
  // 如果节点已被点击,则不应用 hover 样式(可选)  
  if (!cell?.data?.isClicked) { 
    if (cell.shape == "rect") {
      //点击的是节点 ,给节点添加边框颜色和边框宽度
      emitter.emit("node-click", cell.data.zbtxZbcId);
      cell.attr("body/stroke", "#5F95FF");
      cell.attr("body/stroke-width", 1);
    } else if (cell.shape == "edge") {
      //点击的是连线, ,给线添加线颜色和线宽度
      cell.attr("line/stroke", "#5F95FF");
      cell.attr("line/stroke-width", 1);
    }
  } 
  };
   // 定义鼠标滑出`cell:mouseleave` 事件处理函数
  graph.on("cell:mouseleave",handleMouseLeave);


  // 定义 `cell:click` 事件处理函数  
const handleClick = (event) => {  
  const cell = event.cell;  
  // 切换节点的点击状态  
  cell.data.isClicked= !cell.data.isClicked;  
    // 点击事件后,首先遍历所有节点和边,将所有节点和边的样式恢复默认样式   ------开始
    graph.getCells().forEach((cell) => {
      if (cell.isNode()) {
        cell.attr("body/stroke", "#5F95FF");
        cell.attr("body/stroke-width", 1);
      } else if (cell.isEdge()) {
        cell.attr("line/stroke", "#A3B1BF");
        cell.attr("line/stroke-width", 1);
      }
    });
    // 点击事件后,应用点击后的高亮样式  ,首先遍历所有节点和边,将所有节点和边的样式恢复默认样式   ------结束
    edgeAnodeId.value = cell.id; //Id 是你想删除节点或者线的ID
    const cellAll = graph.getCellById(edgeAnodeId.value); // graph.getCellById :可以根据id获取线或者节点的信息; graph.getCells获取所有节点和边的信息
    edgeAnodeIdCell.value = cellAll; ///节点或者线信息
    shape.value = cell.shape; //节点、线类型
    if (cell.shape == "rect") {
      //点击的是节点 ,给节点添加边框颜色和边框宽度
      emitter.emit("node-click", cell.data.zbtxZbcId);
      cell.attr("body/stroke", "#FF5733");
      cell.attr("body/stroke-width", 2);
    } else if (cell.shape == "edge") {
      //点击的是连线, ,给线添加线颜色和线宽度
      cell.attr("line/stroke", "#FF5733");
      cell.attr("line/stroke-width", 3);
    }
};
  // 点击信息 cell:click
  graph.on("cell:click", handleClick);
  // 监听键盘的Delete键按下事件,删除线或者删除节点
  document.addEventListener("keydown", (event) => {
    if (event.key === "Delete" || event.key === "Backspace") {
      if (shape.value == "rect") {
        const downstreamNodes = findDownstreamNodes(graph, edgeAnodeId.value);
        //删除此节点的所有下游节点  graph.getCellById(cell)).concat(node)
        downstreamNodes.forEach((cell) => {
          graph.removeCell(graph.getCellById(cell)); //removeCell(单个): 单个线或者节点删除;removeCells(放的是一个数组):多个线或者节点删除;
        });

        //删除此节点的所有相关的节点
        // const relatedNodes = findRelatedNodes(graph,edgeAnodeId.value);
        // relatedNodes.forEach((relatedNodeId) => {
        //   const relatedNode = graph.getCellById(relatedNodeId);
        //   if (relatedNode) {
        //     graph.removeCells([relatedNode]);
        //   }
        // });
      } else if (shape.value == "edge") {
        //线
        graph.removeCell(edgeAnodeIdCell.value);
      }
    }
  });