zhangyuanlian 6 år sedan
förälder
incheckning
153619c438
4 ändrade filer med 101 tillägg och 41 borttagningar
  1. 25 2
      src/components/FlowChart.vue
  2. 66 24
      src/components/Graph.vue
  3. 6 15
      src/components/LeftTools.vue
  4. 4 0
      src/styles/index.scss

+ 25 - 2
src/components/FlowChart.vue

@@ -3,12 +3,14 @@
     <Tools></Tools>
     <div class="app-main">
       <LeftTools
+        :btns="btns"
         @changeState="changeState"
       ></LeftTools>
       <div class="graph-container">
         <Graph
           :isDragging="isDragging"
-          :isLinking="isLinking"
+          :toLink="toLink"
+          @activeSelectBtn="activeSelectBtn"
         ></Graph>
         <GraphProp></GraphProp>
       </div>
@@ -25,8 +27,19 @@ import GraphProp from './GraphProp'
 export default {
   data () {
     return {
+      btns: [
+        {name: '选择', type: 'select', draggable: false, active: true},
+        {name: '自动插入', type: 'addStartEnd', draggable: false, active: false},
+        {name: '开始', type: 'start', draggable: true, active: false},
+        {name: '结束', type: 'end', draggable: true, active: false},
+        {name: '普通活动', type: 'ordinary', draggable: true, active: false},
+        {name: '块活动', type: 'block', draggable: true, active: false},
+        {name: '子活动', type: 'subFlow', draggable: true, active: false},
+        {name: '转移', type: 'line', draggable: false, active: false},
+        {name: '自转移', type: 'polyline', draggable: false, active: false}
+      ],
       isDragging: false,
-      isLinking: false
+      toLink: false
     }
   },
   components: {
@@ -38,6 +51,16 @@ export default {
   methods: {
     changeState: function (state) {
       this[state.key] = state.value
+    },
+    activeSelectBtn: function () {
+      this.btns.forEach(function (btn) {
+        if (btn.type === 'select') {
+          btn.active = true
+        } else {
+          btn.active = false
+        }
+      })
+      this.toLink = false
     }
   }
 }

+ 66 - 24
src/components/Graph.vue

@@ -4,19 +4,22 @@
       @drop="addNode"
       @dragover.prevent
     >
-      <svg width="100%" height="418" @mousemove="svgMousemove($event)">
+      <svg width="100%" height="418"
+        @mousemove="svgMousemove($event)"
+        @contextmenu="rightMenu($event)"
+        @mousedown.right="svgMouseRightDown"
+        @mouseup="svgMouseUp"
+      >
         <defs>
-          <marker id="end-arrow" viewBox="0 -5 10 10" refX="42" markerWidth="5" markerHeight="5" orient="auto">
-            <path d="M0,-5 L10,0 L0,5"></path>
-          </marker>
-          <marker id="mark-end-arrow" viewBox="0 -5 10 10" refX="7" markerWidth="5" markerHeight="5" orient="auto">
-            <path d="M0,-5 L10,0 L0,5"></path>
+          <marker id="mark-arrow" viewBox="0 0 14 14" refX="8" refY="6" markerWidth="12" markerHeight="12" orient="auto">
+            <path d="M2,2 L10,6 L2,10 L6,6 L2,2"/>
           </marker>
           <marker id="arrow" viewBox="0 0 14 14" refX="30" refY="6" markerWidth="12" markerHeight="12" orient="auto">
             <path d="M2,2 L10,6 L2,10 L6,6 L2,2"/>
           </marker>
         </defs>
         <g class="graph">
+          <path v-show="isLinking" class="link dragline" :d="dragData" marker-end="url(#mark-arrow)"></path>
           <g>
             <path v-for="edge in edges"
                   :key="edge.id"
@@ -29,10 +32,10 @@
           <g>
             <g v-for="node in nodes"
                :key="node.id"
-               :class="['conceptG', {selected: node.selected, isLinking: isLinking}]"
+               :class="['conceptG', {selected: node.selected, toLink: toLink}]"
                :transform="'translate('+node.x+','+node.y+')'"
                @mousedown="nodeMousedown(node)"
-               @mouseup="nodeMouseup"
+               @mouseup="nodeMouseup(node)"
             >
               <circle :r="node.r"></circle>
               <text text-anchor="middle">
@@ -48,6 +51,7 @@
 
 <script>
 var nodeId = 3
+var edgeId = 2
 var testNodes = [
   {id: 1, name: '普通活动', x: 200, y: 200, selected: false, r: 34},
   {id: 2, name: '普通活动', x: 300, y: 300, selected: false, r: 34}
@@ -65,7 +69,10 @@ export default {
       mousedownNode: null,
       mousedownEdge: null,
       selectedNode: null,
-      selectedEdge: null
+      selectedEdge: null,
+      justDrag: true,
+      isLinking: false,
+      dragData: ''
     }
   },
   computed: {},
@@ -74,7 +81,7 @@ export default {
       type: Boolean,
       require: true
     },
-    isLinking: {
+    toLink: {
       type: Boolean,
       require: true
     }
@@ -114,30 +121,61 @@ export default {
       this.unSelectedAll()
       node.selected = !node.selected
       this.mousedownNode = node
+      if (this.toLink) {
+        this.isLinking = true
+        this.justDrag = false
+      }
+    },
+    nodeMouseup: function (node) {
+      if (this.mousedownNode !== node) {
+        var edge = {
+          id: edgeId,
+          source: this.mousedownNode,
+          target: node,
+          selected: false
+        }
+        this.edges.push(edge)
+      }
     },
     linkNodes: function () {
 
+    },
+    rightMenu: function (e) {
+      e.preventDefault()
+      return false
+    },
+    svgMouseRightDown: function () {
+      this.$emit('activeSelectBtn')
+    },
+    svgMouseUp: function () {
+      this.mousedownNode = null
+      this.dragData = ''
+      this.isLinking = false
+      this.justDrag = true
     },
     svgMousemove: function (e) {
       var node = this.mousedownNode
       if (node) {
-        var dx = Math.abs(e.x - node.x - svgDx)
-        var dy = Math.abs(e.y - node.y - svgDy)
-        if (dx > node.r) {
-          node.x = e.x - svgDx
-        } else {
-          node.x = node.x + e.movementX
+        if (this.isLinking) { // link node
+          this.dragData = 'M' + node.x + ',' + node.y +
+                          'L' + (e.x - svgDx) + ',' + (e.y - svgDy)
         }
-        if (dy > node.r) {
-          node.y = e.y - svgDy
-        } else {
-          node.y = node.y + e.movementY
+        if (this.justDrag) { // drag node
+          var dx = Math.abs(e.x - node.x - svgDx)
+          var dy = Math.abs(e.y - node.y - svgDy)
+          if (dx > node.r) {
+            node.x = e.x - svgDx
+          } else {
+            node.x = node.x + e.movementX
+          }
+          if (dy > node.r) {
+            node.y = e.y - svgDy
+          } else {
+            node.y = node.y + e.movementY
+          }
         }
       }
     },
-    nodeMouseup: function () {
-      this.mousedownNode = null
-    },
     clickEdge: function (edge) {
       this.unSelectedAll()
       edge.selected = !edge.selected
@@ -173,7 +211,7 @@ marker {
   fill: #3c39f2;
 }
 
-g.conceptG.isLinking {
+g.conceptG.toLink {
   cursor: crosshair;
 }
 
@@ -222,4 +260,8 @@ path.link {
 path.link:hover {
   stroke: rgb(94, 196, 204);
 }
+
+tspan {
+  user-select: none
+}
 </style>

+ 6 - 15
src/components/LeftTools.vue

@@ -18,19 +18,10 @@
 
 <script>
 export default {
-  data () {
-    return {
-      btns: [
-        {name: '选择', type: 'select', draggable: false, active: true},
-        {name: '自动插入', type: 'addStartEnd', draggable: false, active: false},
-        {name: '开始', type: 'start', draggable: true, active: false},
-        {name: '结束', type: 'end', draggable: true, active: false},
-        {name: '普通活动', type: 'ordinary', draggable: true, active: false},
-        {name: '块活动', type: 'block', draggable: true, active: false},
-        {name: '子活动', type: 'subFlow', draggable: true, active: false},
-        {name: '转移', type: 'line', draggable: false, active: false},
-        {name: '自转移', type: 'polyline', draggable: false, active: false}
-      ]
+  props: {
+    btns: {
+      type: Array,
+      require: true
     }
   },
   methods: {
@@ -41,12 +32,12 @@ export default {
       btn.active = !btn.active
       var linktypes = ['line', 'polyline']
       var state = {
-        key: 'isLinking',
+        key: 'toLink',
         value: false
       }
       if (linktypes.includes(btn.type)) {
         state = {
-          key: 'isLinking',
+          key: 'toLink',
           value: true
         }
       }

+ 4 - 0
src/styles/index.scss

@@ -93,4 +93,8 @@ div:focus{
   display: flex;
   flex-direction: column;
   justify-content: center;
+}
+
+.hidden {
+  display: none
 }