140 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <section class="AiDrawer" :style="{width:`${width}px`,height:`${height}px`}">
 | |
|     <slot name="tools"/>
 | |
|     <div class="resetSignature" @click.stop="handleClean">
 | |
|       <ai-icon icon="iconResetting"/>
 | |
|       <span>重写</span>
 | |
|     </div>
 | |
|     <div v-if="drawPlaceholder" class="placeholder">{{ placeholder }}</div>
 | |
|     <canvas id="drawer" :width="width" :height="height" @mousedown.stop="handleDrawStart($event)"
 | |
|             @mouseup.stop="handleDrawEnd" @mouseleave="handleDrawEnd"
 | |
|             @mousemove.stop="handleDrawing($event)"
 | |
|             @touchstart.stop="handleDrawStart" @touchend.stop="handleDrawEnd" @touchmove="handleDrawing"/>
 | |
|   </section>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| export default {
 | |
|   name: "AiDrawer",
 | |
|   props: {
 | |
|     seal: String,
 | |
|     placeholder: {type: String, default: "请在此处清晰书写你的签名"},
 | |
|     width: {type: Number, default: 640},
 | |
|     height: {type: Number, default: 480}
 | |
|   },
 | |
|   data() {
 | |
|     return {
 | |
|       drawing: false,//判断是否处于绘画中
 | |
|       drawer: {},
 | |
|       drawPlaceholder: true
 | |
|     }
 | |
|   },
 | |
|   watch: {
 | |
|     drawing() {
 | |
|       this.drawPlaceholder = false
 | |
|     }
 | |
|   },
 | |
|   mounted() {
 | |
|     this.initDrawer()
 | |
|   },
 | |
|   methods: {
 | |
|     initDrawer() {
 | |
|       this.$nextTick(() => {
 | |
|         let canvas = document.querySelector("#drawer")
 | |
|         if (canvas) {
 | |
|           this.drawer = canvas?.getContext("2d")
 | |
|           this.drawer.lineWidth = 3
 | |
|           this.drawer.shadowColor = '#333'
 | |
|           this.drawer.strokeStyle = '#333'
 | |
|           this.drawer.shadowBlur = 2
 | |
|         }
 | |
|       })
 | |
|     },
 | |
|     handleDrawStart(e) {
 | |
|       this.drawing = true
 | |
|       const canvasX = e.offsetX
 | |
|       const canvasY = e.offsetY
 | |
|       this.drawer?.beginPath()
 | |
|       this.drawer?.moveTo(canvasX, canvasY)
 | |
|     },
 | |
|     handleDrawEnd() {
 | |
|       this.drawing = false
 | |
|       this.$emit("update:seal", this.drawer.canvas.toDataURL("image/png", 1))
 | |
|     },
 | |
|     handleDrawing(e) {
 | |
|       if (this.drawing) {
 | |
|         const t = e.target?.getBoundingClientRect()
 | |
|         let canvasX
 | |
|         let canvasY
 | |
|         // 根据触发事件类型来进行定位
 | |
|         if (e.type == "touchmove") {
 | |
|           canvasX = e.changedTouches[0].clientX - t.x
 | |
|           canvasY = e.changedTouches[0].clientY - t.y
 | |
|         } else {
 | |
|           canvasX = e.offsetX
 | |
|           canvasY = e.offsetY
 | |
|         }
 | |
|         // 连接到移动的位置并上色
 | |
|         this.drawer?.lineTo(canvasX, canvasY)
 | |
|         this.drawer?.stroke()
 | |
|       }
 | |
|     },
 | |
|     handleClean() {
 | |
|       this.drawer.clearRect(0, 0, this.drawer.canvas.width, this.drawer.canvas.height)
 | |
|       this.drawPlaceholder = true
 | |
|     }
 | |
|   }
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <style lang="scss" scoped>
 | |
| .AiDrawer {
 | |
|   margin: 0 40px;
 | |
|   background: #F7F7F7;
 | |
|   border: 1px solid #CCCCCC;
 | |
|   position: relative;
 | |
| 
 | |
|   #drawer {
 | |
|     display: block;
 | |
|     cursor: crosshair;
 | |
|   }
 | |
| 
 | |
|   .resetSignature {
 | |
|     position: absolute;
 | |
|     width: 76px;
 | |
|     height: 32px;
 | |
|     background: rgba(#000, .5);
 | |
|     border-radius: 16px;
 | |
|     display: flex;
 | |
|     align-items: center;
 | |
|     justify-content: center;
 | |
|     gap: 8px;
 | |
|     color: rgba(#fff, .6);
 | |
|     cursor: pointer;
 | |
|     right: 16px;
 | |
|     top: 16px;
 | |
| 
 | |
|     .AiIcon {
 | |
|       width: auto;
 | |
|       height: auto;
 | |
|     }
 | |
| 
 | |
|     &:hover {
 | |
|       color: #fff;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   .placeholder {
 | |
|     pointer-events: none;
 | |
|     position: absolute;
 | |
|     left: 50%;
 | |
|     top: 50%;
 | |
|     transform: translate(-50%, -50%);
 | |
|     max-width: 407px;
 | |
|     text-align: center;
 | |
|     font-size: 64px;
 | |
|     color: #DDDDDD;
 | |
|   }
 | |
| }
 | |
| </style>
 |