zoukankan      html  css  js  c++  java
  • G6 registerNode afterDraw createNodeBox contextMenu ToolBar 的综合使用

    效果:

     

     代码:

      1 import G6 from "@antv/g6";
      2 
      3 // 提示
      4 const graphDiv = document.getElementById("container");
      5 const descriptionDiv = document.createElement("p");
      6 descriptionDiv.style.padding = 0;
      7 descriptionDiv.style.margin = 0;
      8 descriptionDiv.style.fontSize = "12px";
      9 descriptionDiv.style.color = "#999";
     10 descriptionDiv.innerHTML =
     11   "    *提示:灰色任务代表“禁用”状态,右键进行对任务的删除、启用/禁用操作。";
     12 graphDiv.appendChild(descriptionDiv);
     13 // 右键
     14 const contextMenu = new G6.Menu({
     15   getContent(evt) {
     16     const { dataType } = evt.item.getModel();
     17     const flag = dataType === "disabled";
     18     return `<div eventType = '1' style="cursor:pointer">删除</div>${
     19       flag
     20         ? '<div eventType="2" style="cursor:pointer">启用</div>'
     21         : '<div eventType="3" style="cursor:pointer">禁用</div>'
     22     }`;
     23   },
     24   shouldBegin(evt) {
     25     const { dataType } = evt.item.getModel();
     26     if (dataType && dataType === "root") {
     27       return false;
     28     } else {
     29       return true;
     30     }
     31   },
     32   handleMenuClick: (target, item) => {
     33     console.log(item.getModel());
     34     const eventType = target.getAttribute("eventType");
     35     switch (eventType) {
     36       default:
     37         return;
     38       case "1":
     39         console.log(1, eventType);
     40         break;
     41       case "2":
     42         console.log(2, eventType);
     43         break;
     44       case "3":
     45         console.log(3, eventType);
     46         break;
     47     }
     48   },
     49   offsetX: 16,
     50   offsetY: 0,
     51   itemTypes: ["node"]
     52 });
     53 // 工具栏按钮定制
     54 const toolbar = new G6.ToolBar({
     55   position: { x: 700, y: 10 },
     56   getContent: () => {
     57     return `
     58       <ul>
     59         <li code='switch'>切换</li>
     60         <li code='fitView'>适应</li>
     61       </ul>
     62     `;
     63   },
     64   handleClick(code, graph) {
     65     switch (code) {
     66       case "switch": // 横、纵切换
     67         const controler = graph.get("layoutController");
     68         const { rankdir } = controler.layoutMethod;
     69         if (rankdir === "H") {
     70           controler.updateLayoutCfg({ rankdir: "LR" });
     71         } else {
     72           controler.updateLayoutCfg({ rankdir: "H" });
     73         }
     74         controler.relayout();
     75         graph.fitView();
     76         break;
     77       case "fitView": // 适应屏幕
     78         graph.fitView();
     79         break;
     80       default:
     81         return;
     82     }
     83   }
     84 });
     85 
     86 const ERROR_COLOR = "#F5222D";
     87 const getNodeConfig = (node) => {
     88   if (node.nodeError) {
     89     return {
     90       basicColor: ERROR_COLOR,
     91       fontColor: "#FFF",
     92       borderColor: ERROR_COLOR,
     93       bgColor: "#E66A6C"
     94     };
     95   }
     96   let config = {
     97     basicColor: "#5B8FF9",
     98     fontColor: "#5B8FF9",
     99     borderColor: "#5B8FF9",
    100     bgColor: "#C6E5FF"
    101   };
    102   return config;
    103 };
    104 const nodeBasicMethod = {
    105   createNodeBox: (group, config, w, h, cfg) => {
    106     const nodeError = cfg.nodeError;
    107     /* 最外面的大矩形 */
    108     const container = group.addShape("rect", {
    109       attrs: {
    110         x: 3,
    111         y: 0,
    112          w,
    113         height: h,
    114         fill: config.bgColor,
    115         stroke: config.borderColor,
    116         radius: 2,
    117         cursor: "pointer"
    118       },
    119       name: "rect-shape"
    120     });
    121     /* 左边的粗线 */
    122     group.addShape("rect", {
    123       attrs: {
    124         x: 3,
    125         y: 0,
    126          3,
    127         height: h,
    128         fill: config.basicColor,
    129         radius: 1.5
    130       },
    131       name: "left-border-shape"
    132     });
    133     // 启用、禁用 按钮 外框
    134     const ipRect = group.addShape("rect", {
    135       attrs: {
    136         fill: nodeError ? "transparent" : "#FFF",
    137         stroke: nodeError ? "rgba(255,255,255,0.65)" : null,
    138         radius: 2,
    139         cursor: "pointer",
    140         opacity: 0
    141       },
    142       name: "ip-container-shape"
    143     });
    144     // 启用、禁用 按钮 文字
    145     const ipText = group.addShape("text", {
    146       attrs: {
    147         text: cfg.ip,
    148         x: 40,
    149         y: 19,
    150         fontSize: 12,
    151         textAlign: "left",
    152         textBaseline: "middle",
    153         fill: nodeError ? "rgba(255,255,255,0.85)" : "rgba(0,0,0,0.65)",
    154         cursor: "pointer",
    155         opacity: 0
    156       },
    157       name: "ip-text-shape"
    158     });
    159     // 移除 按钮外框
    160     const moveItemRect = group.addShape("rect", {
    161       attrs: {
    162         fill: nodeError ? "transparent" : "#E66A6C",
    163         stroke: nodeError ? "rgba(255,255,255,0.65)" : null,
    164         radius: 2,
    165         cursor: "pointer",
    166         opacity: 0
    167       },
    168       name: "remove-rect"
    169     });
    170     // 移除 按钮文字
    171     const moveItemText = group.addShape("text", {
    172       attrs: {
    173         text: "移除",
    174         x: 40,
    175         y: 19,
    176         fontSize: 12,
    177         textAlign: "left",
    178         textBaseline: "middle",
    179         fill: nodeError ? "rgba(255,255,255,0.85)" : "rgba(0,0,0,0.65)",
    180         cursor: "pointer",
    181         opacity: 0
    182       },
    183       name: "remove-text"
    184     });
    185     const ipBBox = ipText.getBBox();
    186     const ipTextX = w - 20 - 2 * ipBBox.width;
    187     const ipTextY = ipBBox.minY - 5;
    188     const moveItemTextX = w - 10 - ipBBox.width;
    189     const moveItemTextY = ipBBox.minY - 5;
    190     ipText.attr({
    191       x: ipTextX
    192     });
    193     ipRect.attr({
    194       x: ipTextX - 4,
    195       y: ipTextY,
    196        ipBBox.width + 8,
    197       height: ipBBox.height + 10
    198     });
    199     moveItemText.attr({
    200       x: moveItemTextX + 4
    201     });
    202     moveItemRect.attr({
    203       x: moveItemTextX,
    204       y: moveItemTextY,
    205        ipBBox.width + 8,
    206       height: ipBBox.height + 10
    207     });
    208     // 任务 名称文字
    209     group.addShape("text", {
    210       attrs: {
    211         text: cfg.name,
    212         x: 12,
    213         y: 19,
    214         fontSize: 14,
    215         fontWeight: 700,
    216         textAlign: "left",
    217         textBaseline: "middle",
    218         fill: config.fontColor,
    219         cursor: "pointer"
    220       },
    221       name: "name-text-shape"
    222     });
    223     // 任务 内容文字
    224     group.addShape("text", {
    225       attrs: {
    226         text: cfg.keyInfo,
    227         x: 12,
    228         y: 45,
    229         fontSize: 14,
    230         textAlign: "left",
    231         textBaseline: "middle",
    232         fill: config.fontColor,
    233         cursor: "pointer"
    234       },
    235       name: "bottom-text-shape"
    236     });
    237     return container;
    238   },
    239   afterDraw: (cfg, group) => {
    240     // 添加 移入/移出 事件
    241     const ipLine = group.find(
    242       (element) => element.get("name") === "ip-container-shape"
    243     );
    244     const ipBG = group.find(
    245       (element) => element.get("name") === "ip-text-shape"
    246     );
    247     const removeRect = group.find(
    248       (element) => element.get("name") === "remove-rect"
    249     );
    250     const removeText = group.find(
    251       (element) => element.get("name") === "remove-text"
    252     );
    253     const onMouseEnter = () => {
    254       ipLine && ipLine.attr("opacity", 1);
    255       ipBG && ipBG.attr("opacity", 1);
    256       removeRect && removeRect.attr("opacity", 1);
    257       removeText && removeText.attr("opacity", 1);
    258       graph.get("canvas").draw();
    259     };
    260     const onMouseLeave = () => {
    261       ipLine && ipLine.attr("opacity", 0);
    262       ipBG && ipBG.attr("opacity", 0);
    263       removeRect && removeRect.attr("opacity", 0);
    264       removeText && removeText.attr("opacity", 0);
    265       graph.get("canvas").draw();
    266     };
    267     const lineclick = (e) => {
    268       console.log(e.target.getParent().get("item").getModel());
    269     };
    270     group.on("mouseenter", () => {
    271       onMouseEnter();
    272     });
    273     group.on("mouseleave", () => {
    274       onMouseLeave();
    275     });
    276     ipBG &&
    277       ipBG.on("click", (e) => {
    278         lineclick(e);
    279       });
    280     ipLine &&
    281       ipLine.on("click", (e) => {
    282         lineclick(e);
    283       });
    284   }
    285 };
    286 G6.registerNode(
    287   "card-node",
    288   {
    289     draw: (cfg, group) => {
    290       const config = getNodeConfig(cfg);
    291       /* 最外面的大矩形 */
    292       const container = nodeBasicMethod.createNodeBox(
    293         group,
    294         config,
    295         140,
    296         60,
    297         cfg
    298       );
    299       return container;
    300     },
    301     afterDraw: nodeBasicMethod.afterDraw,
    302     getAnchorPoints() {
    303       return [
    304         [0.5, 0],
    305         [0.5, 1],
    306         [0, 0.5],
    307         [1, 0.5]
    308       ];
    309     }
    310   },
    311   "rect"
    312 );
    313 G6.registerNode("sql", {
    314   drawShape(cfg, group) {
    315     const rect = group.addShape("rect", {
    316       attrs: {
    317          100,
    318         height: 50,
    319         radius: 5,
    320         stroke: "#5B8FF9",
    321         fill: "#C6E5FF"
    322       },
    323       name: "rect-shape"
    324     });
    325     group.addShape("text", {
    326       attrs: {
    327         text: cfg.name,
    328         x: 50,
    329         y: 25,
    330         fill: "#00287E",
    331         fontSize: 14,
    332         textAlign: "center",
    333         textBaseline: "middle",
    334         fontWeight: "bold"
    335       },
    336       name: "text-shape"
    337     });
    338     return rect;
    339   },
    340   // 设置 节点 之间 锚点 连接位置
    341   getAnchorPoints() {
    342     return [
    343       [0.5, 0], // top-center
    344       [0.5, 1] // bottom-center
    345     ];
    346   }
    347 });
    348 const data = {
    349   nodes: [
    350     {
    351       id: "1",
    352       dataType: "root",
    353       name: "等级1",
    354       type: "sql"
    355     },
    356     {
    357       name: "任务1",
    358       ip: "启用",
    359       nodeError: true,
    360       keyInfo:
    361         "lsy3.novalocalsy3.novalocalsy3.novalocalsy3.novalocalsy3.novaloca",
    362       id: "2",
    363       comboId: "A",
    364       dataType: "disabled",
    365       type: "card-node"
    366     },
    367     {
    368       name: "任务1",
    369       ip: "启用",
    370       nodeError: true,
    371       keyInfo: "lsy3.novaloca",
    372       id: "12",
    373       comboId: "A",
    374       dataType: "disabled",
    375       type: "card-node"
    376     },
    377     {
    378       name: "任务1",
    379       ip: "启用",
    380       nodeError: true,
    381       keyInfo: "lsy3.novaloca",
    382       id: "22",
    383       comboId: "A",
    384       dataType: "disabled",
    385       type: "card-node"
    386     },
    387     {
    388       name: "任务1",
    389       ip: "启用",
    390       nodeError: true,
    391       keyInfo: "lsy3.novaloca",
    392       id: "32",
    393       comboId: "A",
    394       dataType: "disabled",
    395       type: "card-node"
    396     },
    397     {
    398       id: "3",
    399       name: "任务2",
    400       comboId: "A",
    401       ip: "禁用",
    402       nodeError: false,
    403       keyInfo: "lsy3.novaloca",
    404       type: "card-node"
    405     },
    406     {
    407       id: "13",
    408       name: "任务2",
    409       comboId: "A",
    410       ip: "禁用",
    411       nodeError: false,
    412       keyInfo: "lsy3.novaloca",
    413       type: "card-node"
    414     },
    415     {
    416       id: "4",
    417       dataType: "root",
    418       name: "等级2",
    419       type: "sql"
    420     },
    421     {
    422       id: "5",
    423       name: "任务1",
    424       comboId: "B",
    425       ip: "禁用",
    426       nodeError: false,
    427       keyInfo: "lsy3.novaloca",
    428       type: "card-node"
    429     },
    430     {
    431       id: "6",
    432       name: "任务2",
    433       comboId: "B",
    434       ip: "禁用",
    435       nodeError: false,
    436       keyInfo: "lsy3.novaloca",
    437       type: "card-node"
    438     },
    439     {
    440       id: "7",
    441       dataType: "root",
    442       name: "等级3",
    443       type: "sql"
    444     },
    445     {
    446       id: "8",
    447       name: "任务1",
    448       comboId: "C",
    449       ip: "禁用",
    450       nodeError: false,
    451       keyInfo: "lsy3.novaloca",
    452       type: "card-node"
    453     },
    454     {
    455       id: "9",
    456       name: "任务2",
    457       comboId: "C",
    458       ip: "禁用",
    459       nodeError: false,
    460       keyInfo: "lsy3.novaloca",
    461       type: "card-node"
    462     }
    463   ],
    464   edges: [
    465     {
    466       source: "1",
    467       target: "2"
    468     },
    469     {
    470       source: "1",
    471       target: "12"
    472     },
    473     {
    474       source: "1",
    475       target: "22"
    476     },
    477     {
    478       source: "1",
    479       target: "32"
    480     },
    481     {
    482       source: "1",
    483       target: "3"
    484     },
    485     {
    486       source: "1",
    487       target: "13"
    488     },
    489     {
    490       source: "2",
    491       target: "4"
    492     },
    493     {
    494       source: "12",
    495       target: "4"
    496     },
    497     {
    498       source: "22",
    499       target: "4"
    500     },
    501     {
    502       source: "32",
    503       target: "4"
    504     },
    505     {
    506       source: "3",
    507       target: "4"
    508     },
    509     {
    510       source: "13",
    511       target: "4"
    512     },
    513     {
    514       source: "4",
    515       target: "5"
    516     },
    517     {
    518       source: "4",
    519       target: "6"
    520     },
    521 
    522     {
    523       source: "5",
    524       target: "7"
    525     },
    526     {
    527       source: "6",
    528       target: "7"
    529     },
    530     {
    531       source: "7",
    532       target: "8"
    533     },
    534     {
    535       source: "7",
    536       target: "9"
    537     }
    538   ],
    539   combos: [
    540     {
    541       id: "A"
    542     },
    543     {
    544       id: "B"
    545     },
    546     {
    547       id: "C"
    548     }
    549   ]
    550 };
    551 
    552 const width = 800;
    553 const height = 800;
    554 const graph = new G6.Graph({
    555   container: "container",
    556   width,
    557   height,
    558   layout: {
    559     type: "dagre",
    560     controlPoints: true,
    561     rankdir: "H" // H 从上到下,LR 从左到右
    562   },
    563   plugins: [contextMenu, toolbar],
    564   defaultEdge: {
    565     style: {
    566       endArrow: true,
    567       offset: 45,
    568       stroke: "#C2C8D5"
    569     }
    570   },
    571   modes: {
    572     default: ["drag-canvas", "zoom-canvas"]
    573   },
    574   fitView: true,
    575   defaultCombo: {
    576     type: "rect"
    577   }
    578 });
    579 graph.data(data);
    580 graph.render();
    View Code

    地址:https://codesandbox.io/s/suspicious-bose-qonry?file=/index.js

  • 相关阅读:
    [ios] CGRect
    [.net] c# webservice
    [ios-必看] iOS 下实现解压缩
    [ios-必看] IOS调试技巧:当程序崩溃的时候怎么办 iphone IOS
    [ios-必看] 国人当自强:两岸三地在线编程学习网站大搜罗 [转]
    [ios-必看] WWDC 2013 Session笔记
    [oc] instancetype vs id for Objective-C 【转】
    [ios3-地图] 如何在iOS地图上高效的显示大量数据 [转]
    [ios2] iOS 7新功能的代码例子 【转】
    [ios2]BaaS服务收藏 【转】
  • 原文地址:https://www.cnblogs.com/z-one/p/13998231.html
Copyright © 2011-2022 走看看