G6实现标签拖动连线画流程图

需求描述

列出所有的task标签,拖动task标签在一旁画流程图,打包task的任务名及id和任务的执行流程以json的格式发给后端。

技术栈

G6,vue,h5自带的draggable实现拖动。也稍微利用了ant-design-pro的UI

 

效果截图

<template>
  <div class="mainDiv">
    <!--<h2>任务执行流程</h2>-->
    <div class="leftDiv">
      <div class="font1">
        <a-icon type="tags" />
        <b>TASK信息</b>
      </div>
      <div
        class="container"
        draggable="false">
        <a-input class="input1" placeholder="请输入Task名称"></a-input>
        <a-button
          class="drag-content"
          v-for="(item,cindex) in group"
          :key="cindex"
          draggable="true"
          @dragstart="onDragstart($event)"
          @dragend="onDragend($event)"
          :id="item.id">
          {{item.name}}
        </a-button>
      </div>
    </div>
    <div class="rightDiv">
      <div class="font2">
        <a-icon type="coffee" />
        <b>TASK信息配置图</b>
      </div>
      <div
        class="onDown"
        draggable="false"
        @dragover="onDragover($event)"
        @dragenter="onDragenter($event)"
        @drop="onDrop($event)">
        <a-button @click="lastStep()">撤销</a-button>
        <a-button @click="clear()">清空</a-button>
        <a-button class="submit" @click="submit()">提交</a-button>
        <div id="mountNode"></div>
      </div>
    </div>

  </div>
</template>

<script>
  import G6 from '@antv/g6'
  export default{
    components: {
      G6
    },
    data(){
      return{
        childNode: '', // 存被拖动的元素
        graph:'', // 画笔
        jobTaskList:[],//记录任务表
        // G6
        initData: {
          // 点集
          nodes: [],
          // 边集
          edges: []
        },
        group: [
          { id: '1', name: '任务1' },
          { id: '2', name: '任务2' },
          { id: '3', name: '任务3' },
          { id: '4', name: '任务4' },
          { id: '5', name: '任务5' },
          { id: '6', name: '任务6' },
          { id: '7', name: '任务7' },
          { id: '8', name: '任务8' }
        ],
        loadData: () => {
          return this.$http.get('/service').then(res => {
            return res.result
          })
        },
      }
    },
    methods: {
      onDragstart(event) {
        this.childNode=event.target;
        console.log(this.childNode);
      },
      onDragend(event) {

      },

      onDragenter($event){
        event.preventDefault();
      },
      onDrop2(event){
        event.target.appendChild(this.childNode);
      },
      onDrop(event) {
        this.initData.nodes.push({
            id: this.childNode.id,
            x: event.offsetX,      // 节点横坐标
            y: event.offsetY,      // 节点纵坐标
            label: this.childNode.innerText // 节点文本
          }
        );

        console.log(this.childNode.id);
        var tempY = 9999;
        if(this.initData.nodes.length >= 2){

          var id = this.initData.nodes[this.initData.nodes.length-2].id;
          for(var i=this.initData.nodes.length - 2; i>=0;i--){
            var disX = Math.abs(event.offsetX - this.initData.nodes[i].x);// 记录新结点x值和每个结点的X值得差的绝对
            if(disX < 180 ) { // 如果差值的绝对值小于45就退出循环
              id = this.initData.nodes[i].id;
              break;
            }
            var disY = Math.abs(event.offsetY - this.initData.nodes[i].y);// 记录新结点Y值和每个结点的Y值得差的绝对值
            if(disY < tempY && disY>30){// 取绝对值最小的为原结点
              tempY = disY;
              id = this.initData.nodes[i].id;
            }
          }
          this.initData.edges.push({
            source: id,  // 起始点 id
            target: this.initData.nodes[this.initData.nodes.length-1].id,  // 目标点 id
            label: '' ,  // 边的文本
            style: {
              endArrow: true
            }
          });
        }
        this.childNode.disabled = true;
        this.reRender(); // 重新渲染
      },
      onDragover(event) {
        event.preventDefault();
      },

      // G6
      init() {
        const graph = new G6.Graph({
          container: 'mountNode', // 指定挂载容器
          /*fitView: true,*/
          defaultNode: {
            shape: 'rect',
            size: [ 180, 30 ],
            style: {
              fill: 'steelblue',   // 节点填充色
              stroke: '#fff',      // 节点描边色
              lineWidth: 1         // 节点描边粗细
            },
            // 节点上的标签文本配置
            labelCfg: {
              // 节点上的标签文本样式配置
              style: {
                fill: '#fff'       // 节点标签文字颜色
              }
            }
          },
          width: 700,             // 图的宽度
          height: 550            // 图的高度
        });

        graph.data(this.initData) // 加载数据
        graph.render()     // 渲染
        this.graph = graph;
      },
      // 重新渲染
      reRender(){
        this.graph.data(this.initData) // 加载数据
        this.graph.render()     // 渲染
      },
      // 回退一步
      lastStep() {
        if(this.initData.nodes.length <= 0){// 判断结点数量是否大于0
          alert("已经退回原点啦,不要在点了!");
        }else {
          for(var i=0; i<this.initData.edges.length-1;i++){ // 删除和这个结点相连接的线
            if(this.initData.edges[i].target == this.initData.nodes[this.initData.nodes.length-1].id){// 如果连线的目标结点是最后一个结点的ID则删除这条边
              this.initData.edges.splice(i,1);
            }
          }
          document.getElementById(this.initData.nodes[this.initData.nodes.length-1].id).disabled = false;// 将最后一个结点对应的标签设置为false
          this.initData.nodes.splice(this.initData.nodes.length-1,1);// 删除最后一个结点
          this.reRender();// 重新渲染
        }
      },
      // 清空
      clear(){
        var len = document.getElementsByClassName("drag-content").length;
        for(var i=0;i<len;i++){// 将所有标签disabled属性设置为false
          document.getElementsByClassName("drag-content")[i].disabled = false;
        }
        this.initData.edges = [];
        this.initData.nodes = [];
        this.reRender();// 重新渲染
      },
      // 提交
      submit(){
        this.jobTaskList = [];
        for(let i=0;i<this.initData.nodes.length;i++){
          this.jobTaskList.push({
            id: this.initData.nodes[i].id,
            name: this.initData.nodes[i].label
          });
        }
        console.log(this.jobTaskList);
        this.clear();
        alert("提交成功!");
      }
    },
    mounted(){
      this.init();
    }
  }
</script>
<style lang="stylus">
  .mainDiv{
    background white
  }
  .drag-content{
    width 180px
    background #13c2c2
    margin 5px auto
    margin-left 5px
  }
  .input1{
    width 180px
    margin 5px auto
    margin-left 5px
  }
  b{
    margin-left 5px
  }
  .font1{
      width 200px
      height 30px
      background #CCF5FF
    }
  .font2{
    width 740px
    height 30px
    background #CCF5FF
  }
  .container{
    width 200px
    height 600px
    border 1px solid #C9BBFF
  }
  .onDown{
    width 740px
    height 600px
    border 1px solid #C9BBFF
    text-align:right
  }
  .leftDiv{
    float: left
    margin : 0.05in
    border 1px solid #C9BBFF
  }
  .rightDiv{
    float: left
    margin : 0.05in
    border 1px solid #C9BBFF
  }

</style>

按钮和输入框因为偷懒就用了ant-design-pro的ui,可自行改动切换样式。

项目链接:https://github.com/dave0824/dg_scheduler

注:项目比较乱,没有整理,依托于ant-design-pro开发的,并且ant-design-pro的代码模板都没有删除。还有好多测试版本,

需要的话,凑合着看吧,嘻嘻。

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
AntV G6 是一个基于 JavaScript 的流程图绘制工具,可以帮助用户快速绘制各种类型的流程图。使用 G6 绘制流程图的基本步骤如下: 1. 安装 G6 库 在终端中使用 npm 命令安装 G6 库:npm install @antv/g6。 2. 创建布 使用 G6 提供的 Graph 类创建一个布,示例代码如下: ```javascript import G6 from '@antv/g6'; const graph = new G6.Graph({ container: 'container', width: 800, height: 500, }); ``` 其中,container 参数指定布所在的容器,width 和 height 参数指定布的宽度和高度。 3. 创建节点和边 使用 G6 提供的 API 创建节点和边,示例代码如下: ```javascript graph.addNode('node1', { x: 100, y: 100, size: 50, label: 'Node 1', }); graph.addNode('node2', { x: 300, y: 100, size: 50, label: 'Node 2', }); graph.addEdge('edge1', { source: 'node1', target: 'node2', }); ``` 其中,addNode 方法用于创建节点,addEdge 方法用于创建边。节点和边的属性可以通过第二个参数传入。 4. 渲染布 使用 G6 提供的 render 方法渲染布,示例代码如下: ```javascript graph.render(); ``` 5. 绘制节点和边的样式 使用 CSS 样式表为节点和边设置样式,示例代码如下: ```css .g6-node { fill: #fff; stroke: #666; stroke-width: 1px; } .g6-edge { stroke: #666; stroke-width: 1px; } ``` 以上就是使用 AntV G6 绘制流程图的基本步骤。除了流程图G6 还支持绘制其他类型的图表,例如关系图、树形图等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值