react G6 可视化卡片流程图例子

在这里插入图片描述
edges连接线采用 type=‘polyline’ 折线

style: {
  radius: 20, // 折点圆角
  offset: 20, // 起始最近拐点距离
  controlPoints: [
	{ x: 20, y: 20 }, // 按照坐标点 第一个拐点位置
	{ x: 40, y: 40 }, // 第二个拐点位置
  ]
},
/** 
 * @params g6data {nodes: [], edges: []}
 * @params heightBox canva容器的高度
 */
renderG6Canvas = (g6data, heightBox) => {
    if (!g6data.nodes.length) {
      this.currentGraph && this.currentGraph.destroy();
      return;
    }
    const container = document.getElementById('container');
    const width = container.scrollWidth;
    const height = heightBox || 500;
    // 提前声明卡片搭配的颜色 - 渐变色
    const bgColor = {
      success: 'l(180) 0:#FFFFFF 1:#E2FAEE', // 已完成
      processFailed: 'l(180) 0:#FFFFFF 1:#FFEBEB', // 流程失败
      processException: 'l(180) 0:#FFFFFF 1:#FFF1D5', // 流程异常
      haveInHand: 'l(180) 0:#FFFFFF 1:#EBF3FF', // 进行中
      notStarted: 'l(180) 0:#FFFFFF 1:#F0F2F5' // 未开始
    };

    const tipBgColor = {
      success: '#E8F9E8', // 已完成
      processFailed: '#FAE7E7', // 流程失败
      processException: '#FFECE4', // 流程异常
      haveInHand: '#EBF3FF', // 进行中
      notStarted: '#F0F2F5' // 未开始
    };

    const tipTextColor = {
      success: '#1DC11D', // 已完成
      processFailed: '#F23C3C', // 流程失败
      processException: '#FF9419', // 流程异常
      haveInHand: '#3386F1', // 进行中
      notStarted: '#333333' // 未开始
    };

    G6.registerNode(
      'card-node',
      {
        drawShape: function drawShape(cfg, group) {
          // console.log(cfg, 'cfg');
          // cfg 为 nodes 中的每一组数据
          const r = 2;
          let textColor = '#fff';
          let textBgColor = 'green';
          let titleBgColor = 'l(180) 0:#FFFFFF 1:#E2FAEE';
          let statusTip = '已完成';
          let contentLength;
          switch (cfg.status) {
            // 已完成
            case 'DONE':
              textColor = tipTextColor.success;
              textBgColor = tipBgColor.success;
              titleBgColor = bgColor.success;
              statusTip = '已完成';
              break;
            case 'SKIP':
              textColor = tipTextColor.success;
              textBgColor = tipBgColor.success;
              titleBgColor = bgColor.success;
              statusTip = '已完成';
              break;
            // 进行中
            case 'RUNNING':
              textColor = tipTextColor.haveInHand;
              textBgColor = tipBgColor.haveInHand;
              titleBgColor = bgColor.haveInHand;
              statusTip = '进行中';
              break;
            // 未开始
            case 'EXIST':
              textColor = tipTextColor.notStarted;
              textBgColor = tipBgColor.notStarted;
              titleBgColor = bgColor.notStarted;
              statusTip = '未开始';
              break;
            // 流程异常
            case 'STOP':
              textColor = tipTextColor.processException;
              textBgColor = tipBgColor.processException;
              titleBgColor = bgColor.processException;
              statusTip = '流程异常';
              break;
            // 失败
            case 'ERROR':
              textColor = tipTextColor.processFailed;
              textBgColor = tipBgColor.processFailed;
              titleBgColor = bgColor.processFailed;
              statusTip = '流程失败';
              break;
          }

          if (cfg.key) { // 可以通过if else 判断什么数据展示什么形状和内容
            // 左侧
            const shape = group.addShape('rect', {
              attrs: {
                x: 0,
                y: 0,
                width: 28,
                height: cfg.height,
                fill: '#ddd',
                radius: 20
              },
              name: 'left-box',
              draggable: true
            });

            // 左侧内容 -- 垂直居中的文字可以使用循环
            for (let i = 0; i < cfg.name.length; i++) {
              group.addShape('text', {
                attrs: {
                  textBaseline: 'top',
                  x: 7,
                  y: parseInt(cfg.height / 2) + 20 * i,
                  text: cfg.name[i],
                  fill: 'rgba(17,17,17,1)',
                  fontSize: 14
                },
                name: 'left-title'
              });
            }

            // 总耗时
            group.addShape('text', {
              attrs: {
                textBaseline: 'top',
                y: 10,
                x: 90,
                text: `总耗时`,
                fill: 'rgba(17,17,17,1)',
                fontSize: 14,
                textAlign: 'center'
              },
              name: 'timetext'
            });
            group.addShape('text', {
              attrs: {
                textBaseline: 'top',
                y: 10,
                x: 160,
                text: `${cfg.timeReduce}`,
                fill: 'rgba(89,104,245,1)',
                fontSize: 14,
                textAlign: 'center'
              },
              name: 'timeboxms'
            });

            return shape;
          } else {
            const shape = group.addShape('rect', {
              attrs: {
                x: 0,
                y: 0,
                width: 298,
                height: cfg.height,
                stroke: '#bbb',
                fill: '#fff',
                radius: r
              },
              name: 'main-box',
              draggable: true
            });
            group.addShape('rect', {
              attrs: {
                x: 0,
                y: 0,
                width: 298,
                height: 37,
                fill: titleBgColor,
                radius: [r, r, 0, 0]
              },
              name: 'title-box',
              draggable: true
            });

            // 标题title
            group.addShape('text', {
              attrs: {
                textBaseline: 'top',
                y: 9,
                x: 16,
                text: cfg.name,
                fill: 'rgba(17,17,17,1)',
                fontSize: 16
              },
              name: 'title'
            });

            let textHeight = 46;
            for (let i = 0; i < cfg.newFeatures.length; i++) {
              group.addShape('text', {
                attrs: {
                  textBaseline: 'top',
                  y: textHeight + 24 * i,
                  x: 16,
                  text: cfg.newFeatures[i],
                  fill: 'rgba(51,51,51,1)',
                  fontSize: 14
                },
                name: `detail-text-${i}`
              });
            }

            // hover展示详细内容
            if (cfg.extraList.length) {
              group.addShape('image', {
                attrs: {
                  x: 265,
                  y: cfg.height - 20,
                  width: 14,
                  height: 14,
                  cursor: 'pointer',
                  img: 'https://img.alicdn.com/tfs/TB10g0l37T2gK0jSZFkXXcIQFXa-12-12.svg'
                },
                name: 'hover-icon'
              });
            }

            // 状态背景盒子
            group.addShape('rect', {
              attrs: {
                x: 232,
                y: 9,
                width: 50,
                height: 20,
                fill: textBgColor,
                radius: 5
              },
              name: 'status-box-right',
              draggable: true
            });

            // 状态
            group.addShape('text', {
              attrs: {
                textBaseline: 'top',
                y: 13,
                x: 239,
                lineHeight: 20,
                text: statusTip,
                fill: textColor,
                fontSize: 12
              },
              name: `status-text`
            });

            return shape;
          }
        }
      },
      'single-node'
    );
	
	// g6 的触摸提示框插件
    const tooltip = new G6.Tooltip({
      getContent(e) {
        const data = e?.item?._cfg?.model || {}; // nodes 中的数据
        if (data.extraList.length) {
          let res =
            "<div style='width: 348px;word-wrap:break-word;word-break:break-all;font-size: 14px;text-align: left;line-height: 21px;padding: 10px'><ul>";
          data.extraList.forEach((item) => {
            res += `<li>${item}</li>`;
          });
          res += '</ul></div>';
          return res;
        }
        return '';
      },
      offsetX: -250, // 提示框位置,如遇到位置展示不正确,设置canvas容器css position: 'relative'
      offsetY: -250, 
      itemTypes: ['node'], // 触摸node展示tooltip
      shouldBegin: (evt) => evt?.target?.cfg?.name === 'hover-icon' // 触摸卡片节点名字相同展示tooltip
    });

    const graph = new G6.Graph({
      container: 'container',
      width,
      height,
      fitCenter: false, // edges 水平垂直居中
      fitView: true,
      modes: {
        default: ['drag-canvas', 'drag-node'] //  'drag-node' 拖拽节点
      },
      plugins: [tooltip], // 配置tooltip插件后,上面的才生效
      defaultNode: {
        type: 'card-node'
      },
      defaultEdge: {
        type: 'line',
        style: {
          startArrow: {
            path: G6.Arrow.triangle(9, 9), // 三角形
            fill: '#DCDFE6' // 填充色
          },
          lineWidth: 1
        }
      }
    });
    // console.log(g6data, 'g6data');
    if (this.currentGraph) {
      this.currentGraph.destroy(); // 销毁画布
    }
    graph.data(g6data);
    graph.render();
    this.currentGraph = graph;

    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);
      };
  };

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值