antv/g6 可视化 插件 Tooltip

https://g6.antv.vision/zh/docs/api/Plugins#tooltip
效果:点击蓝色部分,显示蓝色部分内容(内容超出范围)
在这里插入图片描述
主要代码:
在这里插入图片描述

在这里插入图片描述
全部配置代码:
const itemHeight = 16;
const topHeight = 30;

registerBehavior(“dice-er-scroll”, {
getDefaultCfg() {
return {
multiple: true,
};
},
getEvents() {
return {
itemHeight: 16,
click: “click”,
};
},
click(e) {
const { graph } = this;
const { y } = e;
const item = e.item;
const shape = e.shape;
if (!item) {
return;
}
const model = item.getModel();

if (shape.get("name") === "collapse") {
  graph.updateItem(item, {
    collapsed: true,
    size: [240, 50],
  });
  setTimeout(() => graph.layout(), 100);
} else if (shape.get("name") === "expand") {
  graph.updateItem(item, {
    collapsed: false,
    size: [240, 180],
  });
  setTimeout(() => graph.layout(), 100);
}

},
});

registerEdge(“dice-er-edge”, {
draw(cfg, group) {
const edge = group.cfg.item;
const sourceNode = edge.getSource().getModel();
const targetNode = edge.getTarget().getModel();

const sourceIndex = sourceNode.attrs.findIndex((e) => e.key === cfg.sourceKey);

const sourceStartIndex = sourceNode.startIndex || 0;

let sourceY = 15;

if (!sourceNode.collapsed && sourceIndex > sourceStartIndex - 1) {
  sourceY = topHeight + (sourceIndex - sourceStartIndex + 0.5) * itemHeight;
  // 字段需要滚动条时设置
  // sourceY = Math.min(sourceY, 300);
}

const targetIndex = targetNode.attrs.findIndex((e) => e.key === cfg.targetKey);

const targetStartIndex = targetNode.startIndex || 0;

let targetY = 15;

if (!targetNode.collapsed && targetIndex > targetStartIndex - 1) {
  targetY = (targetIndex - targetStartIndex + 0.5) * itemHeight + topHeight;
  // 字段需要滚动条时设置
  // targetY = Math.min(targetY, 300);
}

const startPoint = {
  ...cfg.startPoint,
};
const endPoint = {
  ...cfg.endPoint,
};

startPoint.y = startPoint.y + sourceY;
endPoint.y = endPoint.y + targetY;

let shape;
if (sourceNode.id !== targetNode.id) {
  shape = group.addShape("path", {
    attrs: {
      stroke: "#5B8FF9",
      path: [
        ["M", startPoint.x, startPoint.y],
        [
          "C",
          endPoint.x / 3 + (2 / 3) * startPoint.x,
          startPoint.y,
          endPoint.x / 3 + (2 / 3) * startPoint.x,
          endPoint.y,
          endPoint.x,
          endPoint.y,
        ],
      ],
      endArrow: true,
    },
    name: "path-shape",
  });
} else if (!sourceNode.collapsed) {
  let gap = Math.abs((startPoint.y - endPoint.y) / 3);
  if (startPoint["index"] === 1) {
    gap = -gap;
  }
  shape = group.addShape("path", {
    attrs: {
      stroke: "#5B8FF9",
      path: [
        ["M", startPoint.x, startPoint.y],
        [
          "C",
          startPoint.x - gap,
          startPoint.y,
          startPoint.x - gap,
          endPoint.y,
          startPoint.x,
          endPoint.y,
        ],
      ],
      endArrow: true,
    },
    name: "path-shape",
  });
}

return shape;

},
afterDraw(cfg, group) {
const labelCfg = cfg.labelCfg || {};
const edge = group.cfg.item;
const sourceNode = edge.getSource().getModel();
const targetNode = edge.getTarget().getModel();
if (sourceNode.collapsed && targetNode.collapsed) {
return;
}
const path = group.find((element) => element.get(“name”) === “path-shape”);

const labelStyle = Util.getLabelPosition(path, 0.5, 0, 0, true);
const label = group.addShape("text", {
  attrs: {
    ...labelStyle,
    text: cfg.label || "",
    fill: "#000",
    textAlign: "center",
    stroke: "#fff",
    lineWidth: 1,
  },
});
label.rotateAtStart(labelStyle.rotate);

},
});

registerNode(“dice-er-box”, {
draw(cfg, group) {
const boxStyle = {
stroke: “#096DD9”,
radius: 4,
};
const width = 200;
let height;
const length = cfg.attrs.length + 1;
height = length * itemHeight + topHeight;

const { attrs = [], startIndex = 0, selectedIndex, collapsed, icon } = cfg;
const list = attrs;
const afterList = attrs;
const offsetY = (0.5 - (startIndex % 1)) * itemHeight + topHeight;

// 渲染表名
group.addShape("rect", {
  attrs: {
    fill: boxStyle.stroke,
    height: topHeight,
    width,
    radius: [boxStyle.radius, boxStyle.radius, 0, 0],
  },
  draggable: true,
});

let fontLeft = 12;

if (icon && icon.show !== false) {
  group.addShape("image", {
    attrs: {
      x: 8,
      y: 8,
      height: 16,
      width: 16,
      ...icon,
    },
  });
  fontLeft += 18;
}

group.addShape("text", {
  attrs: {
    y: 22,
    x: fontLeft,
    fill: "#fff",
    text: cfg.label,
    fontSize: 12,
    fontWeight: 500,
  },
});

// 灰色区域
group.addShape("rect", {
  attrs: {
    x: 0,
    y: collapsed ? topHeight : height - 15,
    height: 15,
    width,
    fill: "#eee",
    radius: [0, 0, boxStyle.radius, boxStyle.radius],
    cursor: "pointer",
  },
  name: collapsed ? "expand" : "collapse",
});

// "+" 、"-" 号
group.addShape("text", {
  attrs: {
    x: width / 2 - 6,
    y: collapsed ? topHeight + itemHeight : height,
    text: collapsed ? "+" : "-",
    width,
    fill: "#000",
    radius: [0, 0, boxStyle.radius, boxStyle.radius],
    cursor: "pointer",
  },
  name: collapsed ? "expand" : "collapse",
});

const keyshape = group.addShape("rect", {
  attrs: {
    x: 0,
    y: 0,
    width,
    height: collapsed ? 45 : height,
    ...boxStyle,
  },
  draggable: true,
});

if (collapsed) {
  return keyshape;
}

const listContainer = group.addGroup({});
listContainer.setClip({
  type: "rect",
  attrs: {
    x: -8,
    y: topHeight,
    width: width + 16,
    height: height - topHeight - itemHeight,
  },
});
listContainer.addShape({
  type: "rect",
  attrs: {
    x: 1,
    y: topHeight,
    width: width - 2,
    height: 300 - topHeight,
    fill: "#fff",
  },
  draggable: true,
});

if (afterList) {
  afterList.forEach((e, i) => {
    const isSelected = Math.floor(startIndex) + i === Number(selectedIndex);
    let { key = "", type } = e;
    // 字段名
    const label = type;

    listContainer.addShape("rect", {
      attrs: {
        x: 1,
        y: i * itemHeight - itemHeight / 2 + offsetY,
        width: width - 4,
        height: itemHeight,
        radius: 2,
        lineWidth: 1,
        cursor: "pointer",
        stroke: "#096dd9",
        lineWidth: 0.2,
      },
      name: `item-${Math.floor(startIndex) + i}-content`,
      draggable: true,
    });

    if (!cfg.hideDot) {
      listContainer.addShape("circle", {
        attrs: {
          x: 0,
          y: i * itemHeight + offsetY,
          r: 3,
          stroke: boxStyle.stroke,
          fill: "white",
          radius: 2,
          lineWidth: 1,
          cursor: "pointer",
        },
      });
      listContainer.addShape("circle", {
        attrs: {
          x: width,
          y: i * itemHeight + offsetY,
          r: 3,
          stroke: boxStyle.stroke,
          fill: "white",
          radius: 2,
          lineWidth: 1,
          cursor: "pointer",
        },
      });
    }

    listContainer.addShape("text", {
      attrs: {
        x: 12,
        y: i * itemHeight + offsetY + 6,
        text: label,
        fontSize: 12,
        fill: "#000",
        fontFamily:
          "Avenir,-apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Helvetica Neue,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol",
        full: e,
        fontWeight: isSelected ? 500 : 100,
        cursor: "pointer",
      },
      // name: `item-${Math.floor(startIndex) + i}`,
      // name: `${key}-${label}`,
      // name: key,
      name: cfg.label + "-" + key,
    });
  });
}

return keyshape;

},
getAnchorPoints() {
return [
[0, 0],
[1, 0],
];
},
});

const dataTransform = (data) => {
const nodes = [];
const edges = [];

data.map((node) => {
nodes.push({
…node,
});
if (node.attrs) {
node.attrs.forEach((attr) => {
if (attr.relation) {
attr.relation.forEach((relation) => {
edges.push({
source: node.id,
target: relation.nodeId,
sourceKey: attr.key,
targetKey: relation.key,
label: relation.label,
});
});
}
});
}
});

return {
nodes,
edges,
};
};

const tooltip = new G6.Tooltip({
getContent(e) {
return e.item.getModel().label;
},
trigger: ‘click’,
itemTypes: [‘node’],
shouldBegin: (evt) => {
return evt.shape.get(‘type’) === ‘text’ && !evt.shape?.get(‘name’)
},
})

const toolbar = new G6.ToolBar();

const container = document.getElementById(“container”);

const width = container.scrollWidth;
const height = (container.scrollHeight || 500) - 20;
let graph = new G6.Graph({
container,
width,
height,
defaultNode: {
size: [240, 180],
type: “dice-er-box”,
color: “#5B8FF9”,
style: {
fill: “#9EC9FF”,
lineWidth: 3,
},
labelCfg: {
style: {
fill: “red”,
fontSize: 20,
},
},
},
defaultEdge: {
type: “dice-er-edge”,
style: {
stroke: “#e2e2e2”,
lineWidth: 4,
endArrow: true,
},
},
plugins: [tooltip, toolbar],
// plugins: [toolbar],
modes: {
// default: [“dice-er-scroll”, “zoom-canvas”, “drag-node”, “drag-canvas”],
default: [“dice-er-scroll”, “drag-node”, “drag-canvas”],
},
layout: {
type: “dagre”,
rankdir: “LR”,
align: “UL”,
controlPoints: true,
nodesepFunc: () => 0.2,
ranksepFunc: () => 0.5,
},
animate: true,
});

graph.data(dataTransform(rawData));

graph.render();

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值