Browse Source

Svg+ user experience improvement

luis 7 years ago
parent
commit
0f3e95ced6

+ 5 - 3
browser/vue-flow/src/components/flow/link.vue

@@ -33,7 +33,9 @@ export default {
       if (Math.sqrt(dx * dx + dy * dy) < lineDist) {
         s = Math.max(curve - (lineDist - Math.sqrt(dx * dx + dy * dy)), 0)
       }
-      return `M${this.x1},${this.y1} C${this.x1 + s},${this.y1} ${this.x2 - s},${this.y2} ${this.x2},${this.y2}`
+      s = Math.max(s, 2)
+      const x2 = this.x2 - 7.5
+      return `M${this.x1},${this.y1} C${this.x1 + s},${this.y1} ${x2 - s},${this.y2} ${x2},${this.y2}`
     }
   }
 }
@@ -51,11 +53,11 @@ export default {
   stroke: rgba(0,0,0,0.5);
   stroke-width:4;
   fill: transparent;
-  marker-end:url(#triangle);
+  marker-end:url(#head);
 }
 .flow-link:hover .flow-link__visible {
   stroke: #F00;
-  filter: url(#highlight);
+  filter: url(#highlight-border);
 }
 
 </style>

+ 77 - 25
browser/vue-flow/src/components/flow/manager.vue

@@ -5,19 +5,28 @@
       xmlns:xlink="http://www.w3.org/1999/xlink"
       ref="svg"
       class="view"
+      :class="{'flow-linking':linking || stickySockets}"
       @dragover.prevent
       @drop="managerDrop"
       :width="width"
       :height="height">
       <defs>
+        <marker id="head" orient="auto" markerWidth="2" markerHeight="4"
+                refX="0.1" refY="2">
+          <path d="M0,0 V4 L2,2 Z"/>
+        </marker>
         <filter
           id="highlight-border"
-          x="-100%"
-          y="-100%"
-          width="300%"
-          height="300%">
+          x="-50%"
+          y="-50%"
+          width="200%"
+          height="200%"
+          filterUnits="userSpaceOnUse"
+        >
           <feMorphology in="SourceGraphic" result="MORPH" operator="dilate" radius="1" />
-          <feColorMatrix in="MORPH" result="BORDER" type="matrix" values=".5 0 0 0 0, 0 .5 0 0 0, 0 0 .5 0 0, 0 0 0 1 0"/>
+          <feColorMatrix
+            in="MORPH" result="BORDER" type="matrix"
+            values=".7 0 0 0 0, 0 .7 0 0 0, 0 0 .7 0 0, 0 0 0 1 0"/>
           <feColorMatrix
             result = "matrixOut"
             in = "SourceGraphic"
@@ -34,7 +43,15 @@
           </feMerge>
 
         </filter>
-        <filter id="highlight" x="-100%" y="-100%" width="300%" height="300%">
+        <filter
+          id="highlight"
+          x="-50%"
+          y="-50%"
+          width="200%"
+          height="200%"
+          filterUnits="userSpaceOnUse"
+
+        >
           <feColorMatrix
             result = "matrixOut"
             in = "SourceGraphic"
@@ -46,12 +63,10 @@
             stdDeviation="4" />
           <feMerge>
             <feMergeNode in="blurOut"/>
-            <feMergeNode in="WHITENED"/>
             <feMergeNode in="SourceGraphic"/>
           </feMerge>
 
         </filter>
-
         <filter id="drag-shadow" x="-100%" y="-100%" width="300%" height="300%">
           <feDropShadow dx="0" dy="2" stdDeviation="3"/>
         </filter>
@@ -106,7 +121,8 @@ export default {
     'value': {type: Object, default: () => {}},
     'registry': {type: Object, default: () => {}},
     'width': {type: String, default: '800px'},
-    'height': {type: String, default: '600px'}
+    'height': {type: String, default: '600px'},
+    'stickySockets': {type: Boolean, default: false}
   },
   data () {
     // const cloned = JSON.parse(JSON.stringify(this.value)) // initial?
@@ -114,6 +130,8 @@ export default {
       panzoom: { x: 0, y: 0, zoom: 1 },
       nodeData: { nodes: [], links: [] },
       dragging: null,
+
+      linking: false,
       pointerLink: {active: false, props: {}, src: {}}
     }
   },
@@ -194,8 +212,24 @@ export default {
     this.$nextTick(() => {
       this.$forceUpdate()
     })
+    document.addEventListener('keydown', this.keyDown)
+    document.addEventListener('keyup', this.keyUp)
+  },
+  beforeDestroy () {
+    document.removeEventListener('keydown', this.keyDown)
+    document.removeEventListener('keyup', this.keyUp)
   },
   methods: {
+    keyDown (ev) {
+      if (ev.shiftKey) {
+        this.linking = true
+      }
+    },
+    keyUp (ev) {
+      if (!ev.shiftKey) {
+        this.linking = false
+      }
+    },
     panzoomReset () {
       this.panzoom.x = 0
       this.panzoom.y = 0
@@ -210,21 +244,12 @@ export default {
       const isInput = socket.in !== undefined
       const socketPos = isInput ? nodeRef.inputPos(socket.in) : nodeRef.outputPos(socket.out)
 
-      const p = this.transformedPoint(ev.clientX, ev.clientY)
-      if (isInput) {
-        this.pointerLink.props = {
-          x1: node.x + socketPos.x,
-          y1: node.y + socketPos.y,
-          x2: p.x,
-          y2: p.y
-        }
-      } else {
-        this.pointerLink.props = {
-          x1: p.x,
-          y1: p.y,
-          x2: node.x + socketPos.x,
-          y2: node.y + socketPos.y
-        }
+      // const p = this.transformedPoint(ev.clientX, ev.clientY)
+      this.pointerLink.props = {
+        x1: node.x + socketPos.x,
+        y1: node.y + socketPos.y,
+        x2: node.x + socketPos.x,
+        y2: node.y + socketPos.y
       }
 
       this.pointerLink.active = true
@@ -302,7 +327,6 @@ export default {
     },
     nodeDragStart (ev, i) {
       document.activeElement && document.activeElement.blur()
-      ev.preventDefault()
       var tnode = this.nodeData.nodes[i]
       if (ev.button === 1) {
         // remove related links
@@ -314,6 +338,11 @@ export default {
         return
       }
       if (ev.button !== 0) return // first button
+      if (ev.shiftKey) {
+        console.log('Shifting:', tnode)
+        this.socketPointerDown(tnode.id, ev, {out: 0})
+        return
+      }
       // we can handle with nodeId and a search
       this.nodeData.nodes.splice(i, 1)
       this.nodeData.nodes.push(tnode) // put in last
@@ -445,4 +474,27 @@ function guid () {
   fill:transparent;
 }
 
+/* Override flow-node */
+.flow-node__socket {
+  fill:transparent !important;
+  stroke:transparent !important;
+}
+.flow-linking .flow-node__socket {
+  fill: #AFAFAF !important;
+  stroke: #AFAFAF !important;
+}
+.flow-linking .flow-node__socket:hover {
+  stroke-width:5;
+}
+.flow-linking .flow-node__socket--match {
+  stroke-width:5;
+  stroke:#2a2 !important;
+  fill:#2a2 !important;
+  filter: url(#highlight);
+}
+.flow-linking .flow-node__socket--match:hover {
+  stroke:#0F0 !important;
+  fill:#0F0 !important;
+}
+
 </style>

+ 5 - 5
browser/vue-flow/src/components/flow/node.vue

@@ -156,12 +156,12 @@ export default {
   filter: url(#highlight-border);
 }
 .flow-node__socket {
-  fill: #AFAFAF;
-  stroke: #AFAFAF;
   stroke-width:1;
   cursor:pointer;
-  r:6;
   transition:all .3s;
+
+  fill: #AFAFAF;
+  stroke: #AFAFAF;
 }
 
 .flow-node__socket:hover {
@@ -174,8 +174,8 @@ export default {
   filter: url(#highlight);
 }
 .flow-node__socket--match:hover {
-  stroke:#5F5;
-  fill:#5F5;
+  stroke:#0F0;
+  fill:#0F0;
 }
 
 .flow-node__label {

+ 5 - 3
browser/vue-flow/src/components/flowmain.vue

@@ -44,10 +44,12 @@
           <flow-panel
             :registry="registry"
             @toggleResizeable="funcsResizeable=!funcsResizeable"
+            @toggleStickySockets="managerStickySockets=!managerStickySockets"
           />
 
           <flow-manager
             :registry="registry"
+            :sticky-sockets="managerStickySockets"
             v-model="nodeData"
             @funcsPanelToggle="funcsActive=!funcsActive"
 
@@ -98,9 +100,10 @@ export default {
       },
 
       nodeData: {nodes: [], links: []},
-      funcsSize: '200px',
+      funcsSize: '250px',
       funcsActive: true,
-      funcsResizeable: false
+      funcsResizeable: false,
+      managerStickySockets: false
 
     }
   },
@@ -118,7 +121,6 @@ export default {
         links: v.data.links || []
       }
     })
-
     this.$flowService.on('nodeUpdate', (v) => {
       const node = v.data
       const nd = this.nodeData

+ 44 - 32
browser/vue-flow/src/components/panel.vue

@@ -1,19 +1,36 @@
 <template>
-  <div class="flow-funcs__container" :class="{active:active}">
-    <!-- Menu thing -->
-    <!-- could be handled in different area -->
+  <div
+    class="flow-funcs__container"
+    :class="{active:active}">
     <div class="flow-funcs__control">
-      <button class="item" @click="funcsViewBlocks=!funcsViewBlocks">
-        {{ funcsViewBlocks ? 'list':'blocks' }} view
+      <!-- make this toggle able -->
+      <button
+        class="item"
+        @click="funcsViewBlocks=!funcsViewBlocks">
+        {{ funcsViewBlocks ? 'List':'Blocks' }} view
       </button>
-      <button class="item" @click="$emit('toggleResizeable')">
-        resize
+      <button
+        class="item"
+        @click="$emit('toggleStickySockets')">
+        Sockets
+      </button>
+      <button
+        class="item"
+        @click="$emit('toggleResizeable')">
+        Resize
       </button>
     </div>
+
     <div class="flow-funcs__inner">
-      <hx-collapsible v-for="g in funcsGroups" :key="g">
-        <div class="flow-funcs__header" slot="header">{{ g }}</div>
-        <div class="flow-funcs__group" :class="{blocks:funcsViewBlocks}">
+      <hx-collapsible
+        v-for="g in funcsGroups"
+        :key="g">
+        <div
+          class="flow-funcs__header"
+          slot="header">{{ g }}</div>
+        <div
+          class="flow-funcs__group"
+          :class="{blocks:funcsViewBlocks}">
           <div
             :key="k"
             ref="src"
@@ -59,16 +76,8 @@ export default {
       }
     }
   },
-  mounted () {
-    for (let n of this.$refs.src) {
-      n.addEventListener('dragstart', () => {
-        console.log('Dragging')
-      })
-    }
-  },
   methods: {
     fnDrag (ev, src) {
-      console.log('Dragging started')
       ev.dataTransfer.setData('text/plain', src)
     }
   }
@@ -87,6 +96,23 @@ export default {
 .flow-funcs__container.active {
   width:300px;
 }
+.flow-funcs__control {
+  display:flex;
+  flex-flow:row;
+
+}
+.flow-funcs__control .item{
+  border-right: solid 1px rgba(208,208,208,0.9);
+  font-size:10px;
+  padding:13px;
+  flex:1;
+  height:100%;
+  text-align:center;
+  color:black;
+  text-overflow: ellipsis;
+  min-width:50px;
+  overflow:hidden;
+}
 
 .flow-funcs__inner {
   overflow:hidden;
@@ -154,18 +180,4 @@ export default {
   position:relative;
 }
 
-.flow-funcs__control {
-  display:flex;
-  flex-flow:row;
-
-}
-.flow-funcs__control .item{
-  border-right: solid 1px rgba(208,208,208,0.9);
-  padding:13px;
-  flex:1;
-  height:100%;
-  text-align:center;
-  color:black;
-  font-size:14px;
-}
 </style>

+ 1 - 1
browser/vue-flow/src/router/index.js

@@ -1,6 +1,6 @@
 import Vue from 'vue'
 import Router from 'vue-router'
-import FlowMain from '@/components/flowmain'
+import FlowMain from '@/components/main'
 
 Vue.use(Router)