123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- <template>
- <g
- class="flow-node"
- :class="{'flow-node--dragging':dragging}"
- @mousedown="$emit('nodePointerDown',$event)"
- >
- <rect
- ref="body"
- class="flow-node__body"
- :class="{'flow-node__body--dragging':dragging}"
- v-bind="bodyProps"
- />
- <text
- ref="label"
- class="flow-node__label"
- v-bind="labelProps">
- {{ label }}
- </text>
- <!-- input -->
- <circle
- class="flow-node__socket flow-node__socket--inputs"
- v-for="(inp,i) in inputs"
- v-bind="inputProps(i)"
- :data-nodeid="id"
- :data-in="i"
- :class="{'flow-node__socket--match': inp == match.in}"
- :key="'in'+i"
- @mousedown.stop.prevent="socketPointerDown($event, {in:i})"
- />
- <!-- output -->
- <circle
- v-if="output"
- class="flow-node__socket flow-node__socket--outputs"
- :data-nodeid="id"
- :data-out="0"
- :key="'out'+0"
- :class="{ 'flow-node__socket--match': output == match.out}"
- v-bind="outputProps(0)"
- @mousedown.stop.prevent="socketPointerDown($event, {out:0})"
- />
- </g>
- </template>
- <script>
- export default {
- name: 'FlowNode',
- props: {
- 'id': {type: String, required: true},
- 'label': {type: String, default: ''},
- 'type': {type: String, default: ''},
- 'inputs': {type: Array, default: () => []},
- 'output': {type: String, default: ''},
- 'match': {type: Object, default: () => {}},
- 'dragging': {type: Boolean, default: false},
- 'color': {type: String, default: '#777'},
- 'textColor': {type: String, default: '#fff'}
- // 'value': {type: Object, default: () => {}}
- },
- data () {
- return {
- // maintain reference here?
- labelRect: {x: 0, y: 0, width: 0, height: 0},
- bodyRect: {x: 0, y: 0, width: 0, height: 0}
- }
- },
- computed: {
- labelProps () {
- return {
- x: -this.labelRect.width / 2,
- y: 5,
- fill: this.textColor
- }
- },
- bodyProps () {
- const width = this.labelRect.width + 32
- const rect = {
- x: -width / 2,
- y: -50,
- width: width,
- height: 100,
- fill: this.color
- }
- if (this.type === 'circle') {
- rect.rx = width
- rect.ry = width
- }
- return rect
- },
- inputProps () {
- return (i) => {
- const {x, y} = this.inputPos(i)
- return {
- transform: `translate(${x} ${y})`,
- r: 5
- }
- }
- },
- outputProps () {
- return (i) => {
- const {x, y} = this.outputPos(i)
- return {
- transform: `translate(${x} ${y})`,
- r: 5
- }
- }
- }
- },
- watch: {
- // the only thing now that affects geometry
- 'label' () {
- this.$nextTick(() => {
- this.labelRect = this.$refs.label.getBBox()
- })
- }
- },
- mounted () {
- // After render
- this.$nextTick(() => { // after mount we reupdate with new values
- if (!this.$refs.label) return
- this.labelRect = this.$refs.label.getBBox()
- this.$forceUpdate()
- })
- },
- methods: {
- inputPos (i) {
- const ilen = this.inputs.length
- if (ilen === 0) return {}
- const d = this.bodyProps.height / (ilen * 2)
- return {
- x: this.bodyProps.x + 8,
- y: this.bodyProps.y + d + (i * 2 * d)
- }
- },
- outputPos (i) {
- const rect = this.bodyProps
- return {
- x: rect.x + rect.width - 8,
- y: 0
- }
- },
- socketPointerDown (ev, socket) {
- this.$emit('socketPointerDown', ev, socket)
- }
- }
- }
- </script>
- <style lang="scss">
- .flow-node {
- filter: url(#highlight-border);
- }
- svg:not(.activity) .flow-node:hover .flow-node__body{
- stroke-width:1;
- stroke:black;
- cursor:move;
- }
- .flow-node__socket {
- stroke-width:1;
- cursor:pointer;
- fill: #AFAFAF;
- stroke: #AFAFAF;
- }
- .flow-node__socket:not(.flow-node__socket--match):hover {
- stroke-width:10;
- }
- .flow-node__socket--match {
- stroke-width:10;
- stroke:#2a2;
- fill:#2a2;
- filter: url(#highlight-border);
- }
- .flow-node__label {
- stroke:none;
- pointer-events:none;
- user-select:none;
- fill:white;
- }
- </style>
|