| 1 | <!-- |
| 2 | |
| 3 | Simple Arrow |
| 4 | |
| 5 | <arrow x1="10" y1="20" x2="100" y2="200" color="green" width="3" /> |
| 6 | |
| 7 | <arrow v-bind="{ x1:10, y1:10, x2:200, y2:200 }"/> |
| 8 | |
| 9 | --> |
| 10 | |
| 11 | <script setup lang="ts"> |
| 12 | import { onClickOutside } from '@vueuse/core' |
| 13 | import { ref } from 'vue' |
| 14 | import { makeId } from '../logic/utils' |
| 15 | |
| 16 | defineProps<{ |
| 17 | x1: number | string |
| 18 | y1: number | string |
| 19 | x2: number | string |
| 20 | y2: number | string |
| 21 | width?: number | string |
| 22 | color?: string |
| 23 | twoWay?: boolean |
| 24 | }>() |
| 25 | |
| 26 | const emit = defineEmits(['dblclick', 'clickOutside']) |
| 27 | |
| 28 | const id = makeId() |
| 29 | |
| 30 | const markerAttrs = { |
| 31 | markerUnits: 'strokeWidth', |
| 32 | markerHeight: 7, |
| 33 | refY: 3.5, |
| 34 | orient: 'auto', |
| 35 | } |
| 36 | |
| 37 | const clickArea = ref<HTMLElement>() |
| 38 | onClickOutside(clickArea, () => emit('clickOutside')) |
| 39 | </script> |
| 40 | |
| 41 | <template> |
| 42 | <svg |
| 43 | class="absolute left-0 top-0" |
| 44 | :width="Math.max(+x1, +x2) + 50" |
| 45 | :height="Math.max(+y1, +y2) + 50" |
| 46 | > |
| 47 | <defs> |
| 48 | <marker :id="id" markerWidth="10" refX="9" v-bind="markerAttrs"> |
| 49 | <polygon points="0 0, 10 3.5, 0 7" :fill="color || 'currentColor'" @dblclick="emit('dblclick')" /> |
| 50 | </marker> |
| 51 | <marker v-if="twoWay" :id="`${id}-rev`" markerWidth="20" refX="11" v-bind="markerAttrs"> |
| 52 | <polygon points="20 0, 10 3.5, 20 7" :fill="color || 'currentColor'" @dblclick="emit('dblclick')" /> |
| 53 | </marker> |
| 54 | </defs> |
| 55 | <line |
| 56 | :x1 :y1 :x2 :y2 |
| 57 | :stroke="color || 'currentColor'" |
| 58 | :stroke-width="width || 2" |
| 59 | :marker-end="`url(#${id})`" |
| 60 | :marker-start="twoWay ? `url(#${id}-rev)` : 'none'" |
| 61 | @dblclick="emit('dblclick')" |
| 62 | /> |
| 63 | <line |
| 64 | ref="clickArea" |
| 65 | :x1 :y1 :x2 :y2 |
| 66 | stroke="transparent" |
| 67 | stroke-linecap="round" |
| 68 | :stroke-width="20" |
| 69 | @dblclick="emit('dblclick')" |
| 70 | /> |
| 71 | </svg> |
| 72 | </template> |
| 73 |