关于vue.js:vueG6-图形化

42次阅读

共计 6577 个字符,预计需要花费 17 分钟才能阅读完成。

性能形容 x6(注:id 为 123)

1、g6 装置
2、自定义元素(平行四边形)
3、新增、编辑、删除
4、关系新增、编辑、删除
5、悬浮展现气泡
6、元素拖拽获取地位
7、元素显示与暗藏
8、悬停关联线高亮线两边元素
9、选中元素,高亮以后元素及关系兄弟节点及线
10、点击空白处,革除标记状态

g6 装置

npm install --save @antv/g6

初始化画布

plugins:存储的为插件容器
container:String | HTMLElement,必须,在 Step 1 中创立的容器 id 或容器自身
width:图的宽度
height:图的高度
fitView:视图居中
defaultNode:默认元素款式
defaultEdge:默认线款式(设置透明度为 0.2,避免线太多,看着错乱)

this.graph = new G6.Graph({plugins: ['tooltip'], // 配置  插件
    container: "g-container", // String | HTMLElement,必须,在 Step 1 中创立的容器 id 或容器自身
    width: 800, // Number,必须,图的宽度
    height: 500, // Number,必须,图的高度
    fitView: true,
    defaultNode: {size: [34, 34],
      style: {
        fill: "#ffffff",
        stroke: "rgba(0,0,0,.35)",
        lineWidth: 2,
        cursor: "pointer",
        radius: [2, 2],
        opacity: 0.2,
      },
      labelCfg: {
        style: {fontSize: 14,},
        position: "bottom",
        offset: 5,
      },
    },
    defaultEdge: {
      type: "line",
      color: "#999999",
      style: {
        opacity:0.2,
        cursor: "pointer",
        endArrow: {path: G6.Arrow.vee(6, 5, 0),
          d: 0,
          fill: "red",
          cursor: "pointer",
          lineDash: [0],
        },
      },
      labelCfg: {
        autoRotate: true,
        style: {
          background: {
            fill: "#ffffff",
            stroke: "#000000",
            padding: [2, 2, 2, 2],
            radius: 2,
            cursor: "pointer",
          },
        },
      },
    },
    },
    modes: {
      default: [
        {
          type: "zoom-canvas",
          enableOptimize: true,
          optimizeZoom: 0.9,
        },
        {
          type: "drag-canvas",
          enableOptimize: true,
        },
        "drag-node",
        "brush-select",
        "click-select",
      ],
    },
  });

读取 Step 2 中的数据源到图上

this.graph.data(this.data); // 读取 Step 2 中的数据源到图上

渲染图

this.graph.render(); // 渲染图

气泡悬浮提醒(插件)

// 提醒
  const tooltip = new G6.Tooltip({
    offsetX: 10,
    offsetY: 40,
    getContent: (e) => {const outDiv = document.createElement("div");
      outDiv.style.width = "fit-content";
      outDiv.style.height = "fit-content";
      const model = e.item.getModel();
      if (e.item.getType() === "node") {// 判断是元素还是关系线
        outDiv.innerHTML = `${model.id}`;
      } else {const source = e.item.getSource();
        const target = e.item.getTarget();
        outDiv.innerHTML = ` 起源:${source.getModel().id}<br/> 去向:${target.getModel().id
        }`;
      }
      return outDiv;
    },
  });

自定义元素

// 自定义一个名为 quadrilateral 的节点,通过数据 type 来判断元素
      G6.registerNode(
        "quadrilateral",
        {draw(cfg, group) {const size = this.getSize(cfg); // 转换成 [width, height] 的模式
            const color = cfg.color;
            const width = size[0];
            const height = size[1];
            //  / 1 \
            // 4     2
            //  \ 3 /
            const path = [["M", -width / 4, 0 - height / 1.5], // 上部顶点
              ["L", width / 2, 0 - height / 1.5], // 右侧顶点
              ["L", width / 4, 0], // 下部顶点
              ["L", -width / 2, 0], // 左侧顶点
              ["Z"], // 关闭
            ];
            const style = {path: path, stroke: color, ...cfg.style};

            // 减少一个 path 图形作为 keyShape
            const keyShape = group.addShape("path", {
              attrs: {...style,},
              draggable: true,
              name: "diamond-keyShape", // 在 G6 3.3 及之后的版本中,必须指定 name,能够是任意字符串,但须要在同一个自定义元素类型中放弃唯一性
            });
            // 返回 keyShape
            return keyShape;
          },
          afterDraw(cfg, group) {const size = this.getSize(cfg); // 转换成 [width, height] 的模式
            const color = cfg.color;
            const width = size[0];
            const height = size[1];
            //  / 1 \
            // 4     2
            //  \ 3 /
            const path = [["M", -width / 4, 0 - height / 1.5], // 上部顶点
              ["L", width / 2, 0 - height / 1.5], // 右侧顶点
              ["L", width / 4, 0], // 下部顶点
              ["L", -width / 2, 0], // 左侧顶点
              ["Z"], // 关闭
            ];
            const style = {path: path, stroke: color, ...cfg.style};

            // 减少一个 path 图形作为 keyShape
            const keyShape = group.addShape("path", {
              attrs: {...style,},
              draggable: true,
              name: "diamond-keyShape", // 在 G6 3.3 及之后的版本中,必须指定 name,能够是任意字符串,但须要在同一个自定义元素类型中放弃唯一性
            });
            // 返回 keyShape
            return keyShape;
          },
        },
        // 留神这里继承了 'single-node'
        "rect"
      );

新增

从内部拖拽到画布上,先获取画布的地位坐标

point = this.graph.getPointByClient(e.clientX, e.clientY)

新增元素(rect 为正方形)

this.graph.addItem("node", {
  x: point.x,// x 坐标
  y: point.y,// y 坐标
  label: "name",
  type: "rect",
  id:'123',
  size: [100, 100],// 大小
  style: {// 款式
    lineWidth: 2,
    stroke: "#00BBEF",
    fill: "#DAF3FF",
  },
  nodeStateStyles: {// 状态款式
    selected: {// 选中款式
      lineWidth: 1,
      stroke: "#00BBEF",
    },
    hover: {// 悬浮款式
      lineWidth: 1,
      stroke: "#00BBEF",
    },
  },
 });

设置选中状态

this.graph.setItemState(item, "selected", true);

勾销选中状态

this.graph.setItemState(item, "selected", false);

设置悬浮状态

this.graph.setItemState(item, "hover", true);

勾销悬浮状态

this.graph.setItemState(item, "hover", false);

编辑更新元素

this.graph.updateItem("123", //id
{
  x: point.x,// x 坐标
  y: point.y,// y 坐标
  label: "name",
  type: "rect",
  id:'123',
  size: [100, 100],// 大小
  style: {// 款式
    lineWidth: 2,
    stroke: "#00BBEF",
    fill: "#DAF3FF",
  },
  nodeStateStyles: {// 状态款式
    selected: {// 选中款式
      lineWidth: 1,
      stroke: "#00BBEF",
    },
    hover: {// 悬浮款式
      lineWidth: 1,
      stroke: "#00BBEF",
    },
  },
 });

删除

this.graph.removeItem('123')

关系线新增

this.graph.addItem("edge", {
  label: "name",
  type: "line",
  id:'edge123',
  target:'node1',// 源
  source:'node2',// 指标
  style: {// 款式
    lineWidth: 2,
    lineDash:[8]// 虚线
  },
  nodeStateStyles: {// 状态款式
    selected: {// 选中款式
      lineWidth: 1,
      stroke: "#00BBEF",
    },
    hover: {// 悬浮款式
      lineWidth: 1,
      stroke: "#00BBEF",
    },
  },
 });

编辑更新关系

this.graph.updateItem("edge123", //id
{
  label: "name",
  type: "line",
  id:'edge123',
  target:'node1',// 源
  source:'node2',// 指标
  style: {// 款式
    lineWidth: 2,
    lineDash:[8]// 虚线
  },
  nodeStateStyles: {// 状态款式
    selected: {// 选中款式
      lineWidth: 1,
      stroke: "#00BBEF",
    },
    hover: {// 悬浮款式
      lineWidth: 1,
      stroke: "#00BBEF",
    },
  },
 });

删除关系

this.graph.removeItem('edge123')

拖拽元素

// 拖动 node 节点
  this.graph.on("node:dragend", (ev) => {console.log(ev);
    let{x,y} = ev.item.getModel()})

元素显示与暗藏

//node 为元素节点,123 为元素的 id
let node = this.graph.findById('123')
// 暗藏
node.hide()
// 显示
node.show()

悬停关联线高亮线两边元素

先监听关联线鼠标移入事件,再监听移除事件
鼠标移入时,高亮线及两边元素
鼠标移出时,勾销线及两边元素高亮

// 鼠标悬停线,高亮相干元素
  this.graph.on("edge:mouseenter", (e) => {e.stopPropagation();
    const source = e.item.getSource();
    const target = e.item.getTarget();
    // 高亮
    this.graph.setItemState(source, "hover", true);
    this.graph.setItemState(target, "hover", true);
    this.graph.setItemState(e.item, "hover", true);
    // 设置层级最前显示(避免被笼罩)source.toFront()
    target.toFront()
    e.item.toFront()
    // 因为初始化了线通明的为 0.2,所有这里把透明度设置 1,不便查看
    this.graph.updateItem(e.item,{style:{opacity:1}
    })
  });
// 鼠标悬停线,勾销高亮相干元素
  this.graph.on("edge:mouseleave", (e) => {e.stopPropagation();
    const source = e.item.getSource();
    const target = e.item.getTarget();
    // 勾销高亮
    this.graph.setItemState(source, "hover", false);
    this.graph.setItemState(target, "hover", false);
    this.graph.setItemState(e.item, "hover", false);
    this.graph.updateItem(e.item,{style:{opacity:0.2}
    })
  });

选中元素,高亮以后元素及关系兄弟节点及线

1、设置所有元素透明度 0.2
2、高亮过后点击元素,透明度为 1
3、判断线的源数据和指标数据是否和以后点击的节点有关系,有则高亮,无则显示暗度

this.graph.on("node:click",ev=>{if(!ev) return
  let {id} = ev.tem.getModel()
  this.graph.setItemState(id,'selected',true)
  ev.item.toFront();
  // 用于存储 id,革除之前的状态
  this.positionId = id
  // 设置所有元素透明度 0.2
  this.graph.getNodes().forEach(node=>{this.graph.updateItem(node,{style:{opacity:0.2}})
  })
  // 高亮以后点击元素
  this.graph.updateItem(ev.item,{style:{opacity:1}})
  // 元素居中
  this.graph.focusItem(ev.item)
  // 高亮关联线及节点
  this.graph.getEdges().forEach(edge=>{if(edge.getSouce() === ev.item){this.graph.updateItem(edge.getTarget(),{style:{opacity:1}})
      this.graph.updateItem(edge,{style:{opacity:1}})
      edge.toFront()}else if(edge.getTarget() === ev.item){this.graph.updateItem(edge.getSouce(),{style:{opacity:1}})
      this.graph.updateItem(edge,{style:{opacity:1}})
      edge.toFront()}else{this.graph.updateItem(edge,{style:{opacity:0.2}})
    }
  })
})

点击空白处,革除标记状态

this.graph.on("canvas:click",()=>{this.graph.getNodes().forEach(node=>{if(this.positionId){
      // 设置所有元素透明度 0.2
      this.graph.updateItem(node,{style:{opacity:0.2}})
      }
    this.graph.clearItemStatus(node)
  
  })
  
  this.graph.getEdges().forEach(edge=>{if(this.positionId){
      // 关联线 0.2
      this.graph.updateItem(edge,{style:{opacity:0.2}})
      }
    this.graph.clearItemStatus(edge)
  })
})

正文完
 0