123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- <template>
- <g>
- <rect
- class="flow-pan-zoom__grid"
- width="100%"
- height="100%"
- fill="url(#grid)"
- />
- <rect
- ref="transformer"
- class="flow-pan-zoom__transformer"
- width="100%"
- height="100%"
- @mousedown="dragStart"/>
- <g
- class="flow-pan-zoom__transformed"
- ref="transform"
- v-bind="transformProps">
- <slot/>
- </g>
- </g>
- </template>
- <script>
- import utils from '@/utils/utils'
- export default {
- name: 'FlowPanZoom',
- props: {
- value: {type: Object, default: () => { return {x: 0, y: 0, zoom: 1} }}
- },
- data () {
- return {
- zoom: this.value.zoom,
- x: this.value.x,
- y: this.value.y,
- moving: false
- }
- },
- computed: {
- transformProps () {
- const transString = 'matrix(' + [
- this.zoom, 0, 0,
- this.zoom, this.x, this.y
- ].join(' ') + ')'
- return {
- transform: transString,
- class: 'flow-pan-zoom__transform ' + this.moving ? 'moving' : ''
- }
- }
- },
- watch: {
- value: {
- handler () {
- this.zoom = this.value.zoom
- this.x = this.value.x
- this.y = this.value.y
- },
- deep: true
- }
- },
- mounted () {
- this.$el.addEventListener('wheel', this.wheel)
- },
- beforeDestroy () {
- this.$el.removeEventListener('wheel', this.wheel)
- },
- methods: {
- // panStart
- dragStart (ev) {
- document.activeElement && document.activeElement.blur()
- if (!(ev.button === 1 || (ev.button === 0 && ev.ctrlKey))) return // first button
- if (ev.target !== this.$refs.transformer) return
- ev.stopPropagation()
- utils.createDrag({
- drag: (ev) => {
- this.moving = true
- this.update(this.x + ev.movementX, this.y + ev.movementY)
- },
- drop: (ev) => {
- this.moving = false
- }
- })
- },
- wheel (ev) {
- ev.preventDefault()
- let deltaY = (ev.deltaY > 0) ? 1 : -1
- deltaY *= (ev.shiftKey) ? 0.3 : 0.07
- const svgRect = this.$refs.transformer.getBoundingClientRect()
- const oX = ev.clientX - svgRect.left
- const oY = ev.clientY - svgRect.top
- const z = Math.max(this.zoom - (deltaY * this.zoom), 0.1)
- var curX = this.x
- var curY = this.y
- var scaleD = z / this.zoom // delta
- var nx = scaleD * (curX - oX) + oX
- var ny = scaleD * (curY - oY) + oY
- this.update(nx, ny, z)
- },
- update (x, y, zoom) {
- if (x) this.x = x
- if (y) this.y = y
- if (zoom) this.zoom = zoom
- this.$emit('input', {x: this.x, y: this.y, zoom: this.zoom})
- },
- transformedPoint (point) {
- const ctm = this.$refs.transform.getCTM()
- return point.matrixTransform(ctm.inverse())
- }
- }
- }
- </script>
- <style>
- .flow-pan-zoom__transformer {
- fill:transparent;
- }
- /*.flow-pan-zoom__transformed {
- transition: transform 0.15s ease;
- }*/
- .flow-pan-zoom__grid {
- fill:transparent;
- pointer-events:none;
- }
- </style>
|