mirror of https://github.com/docusealco/docuseal
				
				
				
			
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							189 lines
						
					
					
						
							4.3 KiB
						
					
					
				
			
		
		
	
	
							189 lines
						
					
					
						
							4.3 KiB
						
					
					
				| <template>
 | |
|   <div class="relative cursor-crosshair select-none">
 | |
|     <img
 | |
|       ref="image"
 | |
|       :src="image.url"
 | |
|       :width="width"
 | |
|       class="border rounded mb-4"
 | |
|       :height="height"
 | |
|       loading="lazy"
 | |
|     >
 | |
|     <div
 | |
|       class="top-0 bottom-0 left-0 right-0 absolute"
 | |
|       @pointerdown="onStartDraw"
 | |
|     >
 | |
|       <FieldArea
 | |
|         v-for="(item, i) in areas"
 | |
|         :key="i"
 | |
|         :ref="setAreaRefs"
 | |
|         :area="item.area"
 | |
|         :field="item.field"
 | |
|         @start-resize="resizeDirection = $event"
 | |
|         @stop-resize="resizeDirection = null"
 | |
|         @start-drag="isMove = true"
 | |
|         @stop-drag="isMove = false"
 | |
|         @remove="$emit('remove-area', item.area)"
 | |
|       />
 | |
|       <FieldArea
 | |
|         v-if="newArea"
 | |
|         :is-draw="true"
 | |
|         :field="{ submitter_uuid: selectedSubmitter.uuid, type: drawField?.type || 'text' }"
 | |
|         :area="newArea"
 | |
|       />
 | |
|     </div>
 | |
|     <div
 | |
|       v-show="resizeDirection || isMove || isDrag || showMask"
 | |
|       id="mask"
 | |
|       ref="mask"
 | |
|       class="top-0 bottom-0 left-0 right-0 absolute z-10"
 | |
|       :class="{ 'cursor-grab': isDrag || isMove, 'cursor-nwse-resize': drawField, [resizeDirectionClasses[resizeDirection]]: !!resizeDirectionClasses }"
 | |
|       @pointermove="onPointermove"
 | |
|       @dragover.prevent
 | |
|       @drop="onDrop"
 | |
|       @pointerup="onPointerup"
 | |
|     />
 | |
|   </div>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| import FieldArea from './area'
 | |
| 
 | |
| export default {
 | |
|   name: 'TemplatePage',
 | |
|   components: {
 | |
|     FieldArea
 | |
|   },
 | |
|   props: {
 | |
|     image: {
 | |
|       type: Object,
 | |
|       required: true
 | |
|     },
 | |
|     areas: {
 | |
|       type: Array,
 | |
|       required: false,
 | |
|       default: () => []
 | |
|     },
 | |
|     selectedSubmitter: {
 | |
|       type: Object,
 | |
|       required: true
 | |
|     },
 | |
|     drawField: {
 | |
|       type: Object,
 | |
|       required: false,
 | |
|       default: null
 | |
|     },
 | |
|     isDrag: {
 | |
|       type: Boolean,
 | |
|       required: false,
 | |
|       default: false
 | |
|     },
 | |
|     number: {
 | |
|       type: Number,
 | |
|       required: true
 | |
|     }
 | |
|   },
 | |
|   emits: ['draw', 'drop-field', 'remove-area'],
 | |
|   data () {
 | |
|     return {
 | |
|       areaRefs: [],
 | |
|       showMask: false,
 | |
|       isMove: false,
 | |
|       resizeDirection: null,
 | |
|       newArea: null
 | |
|     }
 | |
|   },
 | |
|   computed: {
 | |
|     resizeDirectionClasses () {
 | |
|       return {
 | |
|         nwse: 'cursor-nwse-resize',
 | |
|         ew: 'cursor-ew-resize'
 | |
|       }
 | |
|     },
 | |
|     width () {
 | |
|       return this.image.metadata.width
 | |
|     },
 | |
|     height () {
 | |
|       return this.image.metadata.height
 | |
|     }
 | |
|   },
 | |
|   beforeUpdate () {
 | |
|     this.areaRefs = []
 | |
|   },
 | |
|   methods: {
 | |
|     setAreaRefs (el) {
 | |
|       if (el) {
 | |
|         this.areaRefs.push(el)
 | |
|       }
 | |
|     },
 | |
|     onDrop (e) {
 | |
|       this.$emit('drop-field', {
 | |
|         x: e.layerX,
 | |
|         y: e.layerY,
 | |
|         maskW: this.$refs.mask.clientWidth,
 | |
|         maskH: this.$refs.mask.clientHeight,
 | |
|         page: this.number
 | |
|       })
 | |
|     },
 | |
|     onStartDraw (e) {
 | |
|       this.showMask = true
 | |
| 
 | |
|       this.$nextTick(() => {
 | |
|         this.newArea = {
 | |
|           initialX: e.layerX / this.$refs.mask.clientWidth,
 | |
|           initialY: e.layerY / this.$refs.mask.clientHeight,
 | |
|           x: e.layerX / this.$refs.mask.clientWidth,
 | |
|           y: e.layerY / this.$refs.mask.clientHeight,
 | |
|           w: 0,
 | |
|           h: 0
 | |
|         }
 | |
|       })
 | |
|     },
 | |
|     onPointermove (e) {
 | |
|       if (this.newArea) {
 | |
|         const dx = e.layerX / this.$refs.mask.clientWidth - this.newArea.initialX
 | |
|         const dy = e.layerY / this.$refs.mask.clientHeight - this.newArea.initialY
 | |
| 
 | |
|         if (dx > 0) {
 | |
|           this.newArea.x = this.newArea.initialX
 | |
|         } else {
 | |
|           this.newArea.x = e.layerX / this.$refs.mask.clientWidth
 | |
|         }
 | |
| 
 | |
|         if (dy > 0) {
 | |
|           this.newArea.y = this.newArea.initialY
 | |
|         } else {
 | |
|           this.newArea.y = e.layerY / this.$refs.mask.clientHeight
 | |
|         }
 | |
| 
 | |
|         if (this.drawField?.type === 'cells') {
 | |
|           this.newArea.cell_w = this.newArea.h * (this.$refs.mask.clientHeight / this.$refs.mask.clientWidth)
 | |
|         }
 | |
| 
 | |
|         this.newArea.w = Math.abs(dx)
 | |
|         this.newArea.h = Math.abs(dy)
 | |
|       }
 | |
|     },
 | |
|     onPointerup (e) {
 | |
|       if (this.newArea) {
 | |
|         const area = {
 | |
|           x: this.newArea.x,
 | |
|           y: this.newArea.y,
 | |
|           w: this.newArea.w,
 | |
|           h: this.newArea.h,
 | |
|           page: this.number
 | |
|         }
 | |
| 
 | |
|         if ('cell_w' in this.newArea) {
 | |
|           area.cell_w = this.newArea.cell_w
 | |
|         }
 | |
| 
 | |
|         this.$emit('draw', area)
 | |
|       }
 | |
| 
 | |
|       this.showMask = false
 | |
|       this.newArea = null
 | |
|     }
 | |
|   }
 | |
| }
 | |
| </script>
 |