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

【V5】 G6V5.x 版本里,state 更新后,自定义节点无法接收到回调,没有 demo 和说明。非常难实现预期效果。 #6192

Closed
luckyKyle opened this issue Aug 19, 2024 · 7 comments

Comments

@luckyKyle
Copy link

luckyKyle commented Aug 19, 2024

Describe the bug / 问题描述

aaaa

Reproduction link / 重现链接

No response

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

import React, { useRef, useEffect } from "react";

import { ExtensionCategory, Graph, register } from "@antv/g6";
import { GNode } from "@antv/g6-extension-react";
import { CustomNode, Custom_NODE_KEY } from "./CustomNode";

import { registerEvents } from "./register-events";
import { registerPlugins } from "./register-plugins";

import { defaultConfig, mergeSep, mergeEdgeStyle } from "./_helper";
import { usePrevState } from "./usePrevious";

register(ExtensionCategory.NODE, Custom_NODE_KEY, GNode);

export function G6Chart(props) {
 const { data, currentNode, setCurrentNode, fetch, serviceName } = props;

 const $container = useRef(null);
 const $graph = useRef();

 const prevNode = usePrevState(currentNode);

 function init() {
   const graph = new Graph({
     ...defaultConfig,
     container: $container.current,
     data,
     node: {
       type: Custom_NODE_KEY,
       state: {
         selected: {
           fill: "#f00",
           lineDash: 10,
         },
       },
       style: {
         component: (data) => (
           <CustomNode serviceName={serviceName} data={data} graph={graph} />
         ),
       },
     },
     ...mergeSep(defaultConfig.layout, serviceName),
     ...mergeEdgeStyle(serviceName),
   });

   // 注册插件
   registerPlugins.call(graph, fetch);
   // 绑定事件
   registerEvents.call(graph, serviceName, setCurrentNode);

   $graph.current = graph;
   return graph.render();
 }

 useEffect(() => {
   if ($graph.current || !data) return;
   init();
 }, [data]);

 useEffect(() => {
   if (!currentNode.id) return;

   $graph.current.frontElement(currentNode.id);
   $graph.current.setElementState(currentNode.id, "selected");

   //  清理上一个selected status,保持 最后交互的节点高亮
   prevNode.id && $graph.current.setElementState(prevNode.id, "default");

   // 右侧面板时注入 data
   if (!currentNode.data) {
     const data =
       $graph.current.getComboData(currentNode.id) ||
       $graph.current.getNodeData(currentNode.id);

     $graph.current.focusElement(currentNode.id, true);

     return setCurrentNode((d) => ({
       ...d,
       data,
     }));
   }
 }, [currentNode.id]);

 return <div style={{ height: "100%" }} id="container" ref={$container}></div>;
}

G6 Version / G6 版本

🆕 5.x

Operating System / 操作系统

macOS

Browser / 浏览器

Chrome

Additional context / 补充说明

预期能够点击 node 或者 combo 后,实现元素高亮效果;其中 Node 是自定义节点。
No response

@Aarebecca
Copy link
Contributor

对于 React 节点,其没有默认的状态样式,也无法通过 G6 默认交互设置样式,因为自定义的节点实际上是位于 G 节点上方来作为代替节点的,其获取了所有的交互事件,因此你有设置 React 节点的需求,需要自行实现,下面是一个实现的简单示例:

// Your Custom Node
const MyNode = (props) => {
  const {
    graph,
    data: { id, states },
  } = props;

  return (
    <div
      onClick={() => {
        graph.setElementState(id, ['selected']);
      }}
      style={{
        width: 100,
        height: 100,
        border: states.includes('selected') ? '1px solid black' : 'none',
      }}
    >
      Node Content
    </div>
  );
};

// graph options
const graph = new Graph({
  // ...other options
  node: {
    type: Custom_NODE_KEY,
    // ...other options
    style: {
      // ...other options
      // Use function instead arrow function to get `this` context
      component: function (data) {
        return <MyNode data={data} graph={this} />;
      },
    },
  },
});

@luckyKyle
Copy link
Author

luckyKyle commented Aug 19, 2024

setElementState

非常感谢大佬的快速响应和耐心解答!!
上面实例代码我已做更新

但是仍然没有实现预期效果, 预期点击 combo 或node 是能够始终保持唯一的高亮节点。以下我贴上剩余的节点代码。
核心问题是,无论是使用updateNodeData 还是setElementState,在自定义节点里states参数都无法正确响应,感觉未生效。

aaaa

如果只是点击高亮而非唯一性节点高亮,onClick回调在CustomNode就可内聚处理了。

期待再次不吝赐教!~

function CustomNode({ data, graph }) {
  const { name, style, id, states } = data;
  const [width, height] = [260, 60];

  const radius = 4;

  return (
    <Group>
      <Rect
        width={width}
        height={height}
        fill={states.includes("selected") ? "#f00" : style.fill}
        radius={[radius, radius, 0, 0]}
        onClick={(ev) => {
          console.log("🚀 ~ CustomNodeByHive ~ ev:", {
            ev,
            id,
            data,
            states,
            graph,
          });
          graph.setElementState(id, "selected");
          graph.setElementState(id, ["selected"]);
          graph.updateNodeData([
            { id, states: ["selected"], style: { fill: "#f00" } },
          ]);
        }}
      >
        <Text
          text={name}
          textBaseline="center"
          fill="#000"
          fontSize={14}
          dx={10}
          dy={height / 2 - 14}
        />
      </Rect>
    </Group>
  );
}


// NODE
function registerNodeEvents(graph, setCurrentNode) {
  graph.on(NodeEvent.CLICK, (event) => {
    const { id } = event.target;
    const data = graph.getNodeData(id);
    setCurrentNode((d) => ({
      ...d,
      id,
      data,
    }));

    graph.setElementState(id, "selected");
    graph.updateNodeData([
      { id, states: ["selected"], style: { fill: "#f00" } },
    ]);
    graph.draw();
  });
}

// COMBO
function registerComboEvents(graph, setCurrentNode) {
  graph.on(ComboEvent.CLICK, (event) => {
    const { id } = event.target;
    const data = graph.getComboData(id);
    return setCurrentNode((d) => ({
      ...d,
      id,
      data,
    }));
  });

  graph.on(ComboEvent.POINTER_ENTER, (event) => {
    const { target } = event;
    // graph.updateNodeData([
    //   {
    //     id: target.id,
    //   },
    // ]);
    // graph.draw();
  });

  graph.on(ComboEvent.POINTER_OUT, (event) => {
    const { target } = event;
    // graph.updateNodeData([
    //   {
    //     id: target.id,
    //     style: {
    //       lineWidth: 10,
    //     },
    //   },
    // ]);
    // graph.draw();
  });
}

export function registerEvents(serviceName, callback) {
  const _this = this;
  registerNodeEvents(_this, callback);
  registerComboEvents(_this, callback);
}

@Aarebecca
Copy link
Contributor

@luckyKyle 最好能够提供一个线上可运行 demo

@luckyKyle
Copy link
Author

@luckyKyle 最好能够提供一个线上可运行 demo

代码如下,麻烦抽空解惑!

https://stackblitz.com/edit/react-1sfavs-wa1tvd

@Aarebecca
Copy link
Contributor

这边确认了下是 g6-extension-react 的问题,会尽快修复

@luckyKyle
Copy link
Author

这边确认了下是 g6-extension-react 的问题,会尽快修复

[强] 好的,请问有计划在哪个版本大概什么时间会修复?!后续我也会第一时间获取更新。

@Aarebecca
Copy link
Contributor

@luckyKyle 预计今天会发布,届时相关示例你可以参考这个 PR 的内容 #6208

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

2 participants