web仿neo4j(知识图谱)

web仿neo4j(知识图谱)_第1张图片

const container = document.getElementById('container');
const width = container.scrollWidth;
const height = container.scrollHeight || 900;
const graph = new G6.Graph({
  container: 'container',
  width,
  height,
  layout: {
    type: 'force',
    preventOverlap: true,
    linkDistance: 100,         // 可选,边长
    nodeStrength: -100,         // 可选
    edgeStrength: 0.1,        // 可选
    collideStrength: 1,     // 可选
    nodeSize: 50,             // 可选
    alpha: 0.3,               // 可选
    alphaDecay: 0.028,        // 可选
    alphaMin: 0.01,
    onTick: () => {
      graph.refreshPositions();
    },         // 可选
  },
  modes: {
    default: ['zoom-canvas', 'drag-canvas', 'drag-node'],
  },
  defaultNode: {
    size: 50,
    type: "menu-node"
  },
  defaultEdge: {
    style: {
      endArrow: true,
      lineAppendWidth: 4,
    },
    labelCfg: {
      autoRotate: true,
      style: {
        fill: '#1890ff',
        fontSize: 14,
        background: {
          fill: '#ffffff',
          // stroke: '#9EC9FF',
          padding: [2, 2, 2, 2],
          radius: 2,
        },
      },
    },
  },
});

// 截断长文本。length 为文本截断后长度,elipsis 是后缀
const formatText = (text, length = 5, elipsis = "...") => {
  if (!text) return "";
  if (text.length > length) {
    return `${text.substr(0, length)}${elipsis}`;
  }
  return text;
};
// 清除图上所有节点的 selected 状态及相应样式
const clearFocusNodeState = (graph) => {
  const focusNodes = graph.findAllByState("node", "selected");
  focusNodes.forEach((fnode) => {
    graph.setItemState(fnode, "selected", false); // false
  });
};

// 清除图上所有边的 selected 状态及相应样式
const clearFocusEdgeState = (graph) => {
  const focusEdges = graph.findAllByState("edge", "selected");
  focusEdges.forEach((fedge) => {
    graph.setItemState(fedge, "selected", false);
  });
};
const clearFocusItemState = (graph) => {
  if (!graph) return;
  clearFocusNodeState(graph);
  clearFocusEdgeState(graph);
};
G6.registerNode(
  "menu-node",
  {
    draw(cfg, group) {
      let r = 50;
      if (!isNaN(cfg.size)) {
        r = cfg.size / 2;
      } else if (Array.isArray(cfg.size)) {
        r = cfg.size[0] / 2;
      }
      nodebars.forEach((bar) => {
        group.addShape("path", {
          attrs: {
            path: bar.path,
            lineWidth: 0,
            fill: "#D2D5DA",
            cursor: "pointer",
          },
          // must be assigned in G6 3.3 and later versions. it can be any value you want
          name: bar.key,
          title: bar.title,
          visible: false,
        });
        group.addShape("image", {
          attrs: bar.icon,
          style: {
            transform: "translate(-8,38) scale(0.7)",
          },
          // must be assigned in G6 3.3 and later versions. it can be any value you want
          name: bar.key + "icon",
          visible: false,
          capture: false,
        });
      });
      const keyShape = group.addShape("circle", {
        attrs: {
          x: 0,
          y: 0,
          r,
          fill: '#C990C0',
          opacity: 0.8,
          stroke: '#5B8FF9',
          lineWidth: 0,
          cursor: "pointer",
          shadowColor: '#5B8FF9',
          shadowBlur: 0
        },
        name: "aggregated-node-keyShape",
      });

      let labelStyle = {};
      if (cfg.labelCfg) {
        labelStyle = Object.assign(
          labelStyle,
          cfg.labelCfg.style
        );
      }

      if (cfg.label) {
        const text = formatText(cfg.label);
        let labelStyle = {};
        if (cfg.labelCfg) {
          labelStyle = Object.assign(
            labelStyle,
            cfg.labelCfg.style
          );
        }
        group.addShape("text", {
          attrs: {
            text,
            x: 0,
            y: 4,
            textAlign: "center",
            textBaseLine: "alphabetic",
            cursor: "pointer",
            fill: "#fff",
            opacity: 0.85,
            fontWeight: 400,
            pointerEvents: "none",
            // stroke: global.edge.labelCfg.style.stroke,
          },
          name: "text-shape",
          className: "text-shape",
          draggable: true,
          capture: false,
        });
      }
      return keyShape;
    },
    setState: (name, value, item) => {
      const group = item.get("group");
      if (name === "highlight") {
        if (item.hasState("selected")) {
          return;
        }
        const halo = group.find(
          (e) => e.get("name") === "aggregated-node-keyShape"
        );
        const keyShape = item.getKeyShape();
        const colorSet = item.getModel().colorSet;
        if (value) {
          // halo.attr("shadowBlur", 10);
          halo.attr("lineWidth", 3);
        } else {
          // halo && halo.hide();
          // halo.attr("shadowBlur", 0);
          halo.attr("lineWidth", 0);
        }
      } else if (name === "selected") {
        const halo = group.find(
          (e) => e.get("name") === "aggregated-node-keyShape"
        );
        const nodebars = group.findAll((e) =>
          e.get("name").includes("menu")
        );

        const label = group.find(
          (e) => e.get("name") === "text-shape"
        );
        const keyShape = item.getKeyShape();
        const colorSet = item.getModel().colorSet;
        if (value) {
          nodebars.forEach((p) => p.show());
          halo.attr("shadowBlur", 10);
          halo.attr("lineWidth", 3);
          // keyShape.attr("fill", 'yellow');
          label && label.attr("fontWeight", 800);
        } else {
          nodebars.forEach((p) => p.hide());
          halo.attr("shadowBlur", 0);
          halo.attr("lineWidth", 0);
          // keyShape.attr("fill", colorSet.mainFill); // '#2B384E'
          label && label.attr("fontWeight", 400);
        }
      } else if (name.includes("highlight-menu")) {
        let menu = name.split("highlight-")[1];
        let menuShape = group.find(
          (e) => e.get("name") === menu
        );
        if (value) {
          menuShape.attr({
            fill: "#b9b9b9",
          });
        } else {
          menuShape.attr({
            fill: "#D2D5DA",
          });
        }
      }
    },
    update: undefined,
  },
  "aggregated-node"
); // 这样可以继承 aggregated-node 的 setState
const bindListener = (graph) => {
  graph.on("node:mouseenter", (evt) => {
    const { item } = evt;
    const model = item.getModel();
    // const currentLabel = model.label;
    // model.oriFontSize = model.labelCfg.style.fontSize;
    // item.update({
    //     label: model.oriLabel,
    // });
    // model.oriLabel = currentLabel;
    graph.setItemState(item, "highlight", true);
    item.toFront();
  });

  graph.on("node:mouseleave", (evt) => {
    const { item } = evt;
    const model = item.getModel();
    const currentLabel = model.label;
    // item.update({
    //     label: model.oriLabel,
    // });
    model.oriLabel = currentLabel;
    graph.setItemState(item, "highlight", false);
  });

  graph.on("edge:mouseenter", (evt) => {
    const { item } = evt;
    const model = item.getModel();
    const currentLabel = model.label;
    item.update({
      label: model.oriLabel,
    });
    model.oriLabel = currentLabel;
    graph.setItemState(item, "highlight", true);
    item.toFront();
    item.getSource().toFront();
    item.getTarget().toFront();
  });

  graph.on("edge:mouseleave", (evt) => {
    const { item } = evt;
    const model = item.getModel();
    const currentLabel = model.label;
    item.update({
      label: model.oriLabel,
    });
    model.oriLabel = currentLabel;
    graph.setItemState(item, "highlight", false);
  });
  // click node to show the detail drawer
  graph.on("node:click", (evt) => {
    clearFocusItemState(graph);
    const { item } = evt;
    graph.setItemState(item, "selected", true);
  });

  // click edge to show the detail of integrated edge drawer
  graph.on("edge:click", (evt) => {
    clearFocusItemState(graph);
    const { item } = evt;
    // highlight the clicked edge
    graph.setItemState(item, "selected", true);
  });

  // click canvas to cancel all the selected state
  graph.on("canvas:click", (evt) => {
    clearFocusItemState(graph);
    console.log(
      graph.getGroup(),
      graph.getGroup().getBBox(),
      graph.getGroup().getCanvasBBox()
    );
  });
  graph.on("afterupdateitem", (evt) => {
    const nodes = graph.findAll("node", (node) => {
      return node.get("visible");
    });
    const edges = graph.findAll("edge", (edge) => {
      return edge.get("visible");
    });
  });
  graph.on("afteritemvisibilitychange", (evt) => {
    const nodes = graph.findAll("node", (node) => {
      return node.get("visible");
    });
    const edges = graph.findAll("edge", (edge) => {
      return edge.get("visible");
    });
    _this.nodesLength = nodes.length;
    _this.edgesLength = edges.length;
  });
  // graph.on("afterrender", (evt) => {
  //     let chartData = graph.save();
  //     console.log(2142, chartData);
  // });
};
bindListener(graph);
function refreshDragedNodePosition(e) {
  const model = e.item.get('model');
  model.fx = e.x;
  model.fy = e.y;
}
graph.on('node:dragstart', function (e) {
  graph.layout();
  refreshDragedNodePosition(e);
});
graph.on('node:drag', function (e) {
  const forceLayout = graph.get('layoutController').layoutMethods[0];
  forceLayout.execute();
  refreshDragedNodePosition(e);
});
// graph.on('node:dragend', function (e) {
//   e.item.get('model').fx = null;
//   e.item.get('model').fy = null;
// });
fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/relations.json')
  .then((res) => res.json())
  .then((res) => {

    // --------------------------------------------------------------大数据测试
    let data = {
      nodes: res.nodes.map(p => {
        return {
          ...p,
          label: 888
        }
      }),
      edges: res.edges.map(function (edge, i) {
        edge.id = 'edge' + i;
        edge.label = 'sadasd'
        return Object.assign({}, edge);
      }),
    }



    // --------------------------------------------------多边测试
    // const data = {
    //   nodes: [
    //     {
    //       id: 'node1',
    //       x: 50,
    //       y: 350,
    //       label: 'Adsfgdfffffffffffffffffffffffffffffffffffffffs',
    //     },
    //     {
    //       id: 'node2',
    //       x: 250,
    //       y: 150,
    //       label: 'B',
    //     },
    //     {
    //       id: 'node3',
    //       x: 450,
    //       y: 350,
    //       label: 'C',
    //     },
    //   ],
    //   edges: [],
    // };

    // for (let i = 0; i < 10; i++) {
    //   data.edges.push({
    //     source: 'node1',
    //     target: 'node2',
    //     label: `${i}th edge of A-B`,
    //   });
    // }
    // for (let i = 0; i < 5; i++) {
    //   data.edges.push({
    //     source: 'node2',
    //     target: 'node3',
    //     label: `${i}th edge of B-C`,
    //   });
    // }
    // // loop边测试
    // data.edges.push({
    //   source: 'node1',
    //   target: 'node1',
    //   type: "loop",
    //   label: `${1}th edge of B-C`,
    // });
    // data.edges.push({
    //   source: 'node1',
    //   target: 'node1',
    //   type: "loop",
    //   label: `${1}th edge of B-C`,
    // });
    // data.edges.push({
    //   source: 'node1',
    //   target: 'node1',
    //   type: "loop",
    //   label: `${1}th edge of B-C`,
    // });
    // data.edges.push({
    //   source: 'node2',
    //   target: 'node2',
    //   type: "loop",
    //   label: `${1}th edge of B-C`,
    // });
    // data.edges.push({
    //   source: 'node3',
    //   target: 'node3',
    //   type: "loop",
    //   label: `${1}th edge of B-C`,
    // });
    graph.data(data);
    G6.Util.processParallelEdges(data.edges);
    graph.render();
    // setTimeout(() => {
    //   const data = {
    //     nodes: [
    //       {
    //         id: 'node1',
    //         x: 50,
    //         y: 350,
    //         label: 'Adsfgdfffffffffffffffffffffffffffffffffffffffs',
    //       },
    //       {
    //         id: 'node2',
    //         x: 250,
    //         y: 150,
    //         label: 'B',
    //       },
    //       {
    //         id: 'node3',
    //         x: 450,
    //         y: 350,
    //         label: 'C',
    //       },
    //     ],
    //     edges: [],
    //   };

    //   for (let i = 0; i < 10; i++) {
    //     data.edges.push({
    //       source: 'node1',
    //       target: 'node2',
    //       label: `${i}th edge of A-B`,
    //     });
    //   }
    //   for (let i = 0; i < 5; i++) {
    //     data.edges.push({
    //       source: 'node2',
    //       target: 'node3',
    //       label: `${i}th edge of B-C`,
    //     });
    //   }
    //   // loop边测试
    //   data.edges.push({
    //     source: 'node1',
    //     target: 'node1',
    //     type: "loop",
    //     label: `${1}th edge of B-C`,
    //   });
    //   data.edges.push({
    //     source: 'node1',
    //     target: 'node1',
    //     type: "loop",
    //     label: `${1}th edge of B-C`,
    //   });
    //   data.edges.push({
    //     source: 'node1',
    //     target: 'node1',
    //     type: "loop",
    //     label: `${1}th edge of B-C`,
    //   });
    //   data.edges.push({
    //     source: 'node2',
    //     target: 'node2',
    //     type: "loop",
    //     label: `${1}th edge of B-C`,
    //   });
    //   data.edges.push({
    //     source: 'node3',
    //     target: 'node3',
    //     type: "loop",
    //     label: `${1}th edge of B-C`,
    //   });
    //   graph.changeData(data)
    // }, 5000);

    // setTimeout(() => {
    //   const edges = []
    //   for (let i = 0; i < 10; i++) {
    //     edges.push({
    //       source: 'node1',
    //       target: 'node2',
    //       label: `${i}th edge of A-B`,
    //     });
    //   }
    //   for (let i = 0; i < 5; i++) {
    //     edges.push({
    //       source: 'node2',
    //       target: 'node3',
    //       label: `${i}th edge of B-C`,
    //     });
    //   }
    //   // loop边测试
    //   edges.push({
    //     source: 'node1',
    //     target: 'node1',
    //     type: "loop",
    //     label: `${1}th edge of B-C`,
    //   });
    //   edges.push({
    //     source: 'node1',
    //     target: 'node1',
    //     type: "loop",
    //     label: `${1}th edge of B-C`,
    //   });
    //   edges.push({
    //     source: 'node1',
    //     target: 'node1',
    //     type: "loop",
    //     label: `${1}th edge of B-C`,
    //   });
    //   edges.push({
    //     source: 'node2',
    //     target: 'node2',
    //     type: "loop",
    //     label: `${1}th edge of B-C`,
    //   });
    //   edges.push({
    //     source: 'node3',
    //     target: 'node3',
    //     type: "loop",
    //     label: `${1}th edge of B-C`,
    //   });
    //   edges.forEach(p=>{
    //     graph.addItem('edge', p)
    //   })      
    // }, 5000);
  });

if (typeof window !== 'undefined')
  window.onresize = () => {
    if (!graph || graph.get('destroyed')) return;
    if (!container || !container.scrollWidth || !container.scrollHeight) return;
    graph.changeSize(container.scrollWidth, container.scrollHeight);
  };

 

git地址;

https://gitee.com/youmoxiang_1/imitating-neo4j.githttps://gitee.com/youmoxiang_1/imitating-neo4j.git

你可能感兴趣的:(#,neo4j,知识图谱,人工智能)