| 
					
				 | 
			
			
				@@ -0,0 +1,461 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+<template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	<view class="lime-painter" ref="limepainter"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		<view v-if="canvasId && size" :style="styles"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			<!-- #ifndef APP-NVUE --> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			<canvas class="lime-painter__canvas" v-if="use2dCanvas" :id="canvasId" type="2d" :style="size"></canvas> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			<canvas class="lime-painter__canvas" v-else :id="canvasId" :canvas-id="canvasId" :style="size" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				:width="boardWidth * dpr" :height="boardHeight * dpr" :hidpi="hidpi"></canvas> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			<!-- #endif --> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			<!-- #ifdef APP-NVUE --> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			<web-view :style="size" ref="webview" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				src="/uni_modules/lime-painter/hybrid/html/index.html" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				class="lime-painter__canvas" @pagefinish="onPageFinish" @error="onError" @onPostMessage="onMessage"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			</web-view> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			<!-- #endif --> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		</view> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		<slot /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	</view> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+</template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+<script> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	import { parent } from '../common/relation' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	import props from './props' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	import {toPx, base64ToPath, pathToBase64, isBase64, sleep, getImageInfo }from './utils'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//  #ifndef APP-NVUE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	import { canIUseCanvas2d, isPC} from './utils'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	import Painter from './painter'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// import Painter from '@painter' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	const nvue = {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//  #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//  #ifdef APP-NVUE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	import nvue from './nvue' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//  #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	export default { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		name: 'lime-painter', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		mixins: [props, parent('painter'), nvue], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		data() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				use2dCanvas: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				canvasHeight: 150, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				canvasWidth: null, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				parentWidth: 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				inited: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				progress: 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				firstRender: 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				done: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				tasks: [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		computed: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			styles() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return `${this.size}${this.customStyle||''};` + (this.hidden && 'position: fixed; left: 1500rpx;') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			canvasId() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return `l-painter${this._ && this._.uid || this._uid}` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			size() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (this.boardWidth && this.boardHeight) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					return `width:${this.boardWidth}px; height: ${this.boardHeight}px;`; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			dpr() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return this.pixelRatio || uni.getSystemInfoSync().pixelRatio; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			boardWidth() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const {width = 0} = (this.elements && this.elements.css) || this.elements || this 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const w = toPx(width||this.width) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return w || Math.max(w, toPx(this.canvasWidth)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			boardHeight() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const {height = 0} = (this.elements && this.elements.css) || this.elements || this 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const h = toPx(height||this.height) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return h || Math.max(h, toPx(this.canvasHeight)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			hasBoard() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return this.board && Object.keys(this.board).length 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			elements() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return this.hasBoard ? this.board : JSON.parse(JSON.stringify(this.el)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		created() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.use2dCanvas = this.type === '2d' && canIUseCanvas2d() && !isPC 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		async mounted() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			await sleep(30) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			await this.getParentWeith() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.$nextTick(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				setTimeout(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.$watch('elements', this.watchRender, { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						deep: true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						immediate: true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}, 30) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// #ifdef VUE3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		unmounted() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.done = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.inited = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.firstRender = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.progress = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.painter = null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			clearTimeout(this.rendertimer) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// #ifdef VUE2 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		destroyed() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.done = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.inited = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.firstRender = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.progress = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			this.painter = null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			clearTimeout(this.rendertimer) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		methods: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			async watchRender(val, old) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (!val || !val.views || (!this.firstRender ? !val.views.length : !this.firstRender) || !Object.keys(val).length || JSON.stringify(val) == JSON.stringify(old)) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.firstRender = 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.progress = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.done = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				clearTimeout(this.rendertimer) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.rendertimer = setTimeout(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.render(val); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}, this.beforeDelay) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			async setFilePath(path, param) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				let filePath = path 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const {pathType = this.pathType} =  param || this 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (pathType == 'base64' && !isBase64(path)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					filePath = await pathToBase64(path) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} else if (pathType == 'url' && isBase64(path)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					filePath = await base64ToPath(path) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (param && param.isEmit) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.$emit('success', filePath); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return filePath 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			async getSize(args) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const {width} = args.css || args 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const {height} = args.css || args 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (!this.size) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					if (width || height) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						this.canvasWidth = width || this.canvasWidth 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						this.canvasHeight = height || this.canvasHeight 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						await sleep(30); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						await this.getParentWeith() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			canvasToTempFilePathSync(args) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// this.stopWatch && this.stopWatch() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// this.stopWatch = this.$watch('done', (v) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// 	if (v) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// 		this.canvasToTempFilePath(args) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// 		this.stopWatch && this.stopWatch() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// }, { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// 	immediate: true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.tasks.push(args) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if(this.done){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.runTask() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			runTask(){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				while(this.tasks.length){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					const task = this.tasks.shift()	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					 this.canvasToTempFilePath(task) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// #ifndef APP-NVUE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			getParentWeith() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return new Promise(resolve => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					uni.createSelectorQuery() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						.in(this) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						.select(`.lime-painter`) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						.boundingClientRect() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						.exec(res => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							const {width, height} = res[0]||{} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							this.parentWidth = Math.ceil(width||0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							this.canvasWidth = this.parentWidth || 300 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							this.canvasHeight = height || this.canvasHeight||150 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							resolve(res[0]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			async render(args = {}) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if(!Object.keys(args).length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					return console.error('空对象') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.progress = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.done = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// #ifdef APP-NVUE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.tempFilePath.length = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				await this.getSize(args) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const ctx = await this.getContext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				let { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					use2dCanvas, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					boardWidth, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					boardHeight, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					canvas, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					afterDelay 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} = this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (use2dCanvas && !canvas) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					return Promise.reject(new Error('canvas 没创建')); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.boundary = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					top: 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					left: 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					width: boardWidth, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					height: boardHeight 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				this.painter = null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (!this.painter) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					const {width} = args.css || args 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					const {height} = args.css || args 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					if(!width && this.parentWidth) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						Object.assign(args, {width: this.parentWidth}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					const param = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						context: ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						canvas, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						width: boardWidth, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						height: boardHeight, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						pixelRatio: this.dpr, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						useCORS: this.useCORS, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						createImage: getImageInfo.bind(this), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						performance: this.performance, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						listen: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							onProgress: (v) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								this.progress = v 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								this.$emit('progress', v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							onEffectFail: (err) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								this.$emit('faill', err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.painter = new Painter(param) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				try{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// vue3 赋值给data会引起图片无法绘制 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					const { width, height } = await this.painter.source(JSON.parse(JSON.stringify(args))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.boundary.height = this.canvasHeight = height 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.boundary.width = this.canvasWidth = width 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					await sleep(this.sleep); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					await this.painter.render() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					await new Promise(resolve => this.$nextTick(resolve)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					if (!use2dCanvas) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						await this.canvasDraw(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					if (afterDelay && use2dCanvas) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						await sleep(afterDelay); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.$emit('done'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.done = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					if (this.isCanvasToTempFilePath) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						this.canvasToTempFilePath() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							.then(res => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								this.$emit('success', res.tempFilePath) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							.catch(err => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								this.$emit('fail', new Error(JSON.stringify(err))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.runTask() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					return Promise.resolve({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						draw: this.painter, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						node: this.node 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}catch(e){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					//TODO handle the exception 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			canvasDraw(flag = false) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return new Promise((resolve, reject) => this.ctx.draw(flag, () => setTimeout(() => resolve(), this 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					.afterDelay))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			async getContext() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (!this.canvasWidth) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					this.$emit('fail', 'painter no size') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					console.error('[lime-painter]: 给画板或父级设置尺寸') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					return Promise.reject(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (this.ctx && this.inited) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					return Promise.resolve(this.ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const { type, use2dCanvas, dpr, boardWidth, boardHeight } = this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const _getContext = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					return new Promise(resolve => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						uni.createSelectorQuery() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							.in(this) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							.select(`#${this.canvasId}`) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							.boundingClientRect() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							.exec(res => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								if (res) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									const ctx = uni.createCanvasContext(this.canvasId, this); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									if (!this.inited) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+										this.inited = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+										this.use2dCanvas = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+										this.canvas = res; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									// 钉钉小程序框架不支持 measureText 方法,用此方法 mock 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									if (!ctx.measureText) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+										function strLen(str) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+											let len = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+											for (let i = 0; i < str.length; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+												if (str.charCodeAt(i) > 0 && str.charCodeAt(i) < 128) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+													len++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+												} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+													len += 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+												} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+											} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+											return len; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+										} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+										ctx.measureText = text => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+											let fontSize = ctx.state && ctx.state.fontSize || 12; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+											const font = ctx.__font 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+											if (font && fontSize == 12) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+												fontSize = parseInt(font.split(' ')[3], 10); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+											} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+											fontSize /= 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+											return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+												width: strLen(text) * fontSize 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+											}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+										} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									// #ifdef MP-ALIPAY 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									ctx.scale(dpr, dpr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									// #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									this.ctx = ctx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									resolve(this.ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									console.error('[lime-painter] no node') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (!use2dCanvas) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					return _getContext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return new Promise(resolve => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					uni.createSelectorQuery() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						.in(this) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						.select(`#${this.canvasId}`) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						.node() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						.exec(res => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							let {node: canvas} = res && res[0]||{}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							if(canvas) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								const ctx = canvas.getContext(type); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								if (!this.inited) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									this.inited = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									this.use2dCanvas = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									this.canvas = canvas; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								this.ctx = ctx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								resolve(this.ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								console.error('[lime-painter]: no size') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			canvasToTempFilePath(args = {}) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				return new Promise(async (resolve, reject) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					const { use2dCanvas, canvasId, dpr, fileType, quality } = this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					const success = async (res) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							const tempFilePath = await this.setFilePath(res.tempFilePath || res, args) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							const result = Object.assign(res, {tempFilePath}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							args.success && args.success(result) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							resolve(result) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						} catch (e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							this.$emit('fail', e) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					let { top: y = 0, left: x = 0, width, height } = this.boundary || this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// let destWidth = width * dpr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// let destHeight = height * dpr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// #ifdef MP-ALIPAY 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// width = destWidth; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// height = destHeight; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					const copyArgs = Object.assign({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						// x, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						// y, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						// width, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						// height, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						// destWidth, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						// destHeight, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						canvasId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						id: canvasId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						fileType, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						quality, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					}, args, {success}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// if(this.isPC || use2dCanvas) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// 	copyArgs.canvas = this.canvas 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					if (use2dCanvas) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						copyArgs.canvas = this.canvas 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						try{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							// #ifndef MP-ALIPAY 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							const oFilePath = this.canvas.toDataURL(`image/${args.fileType||fileType}`.replace(/pg/, 'peg'), args.quality||quality) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							if(/data:,/.test(oFilePath)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								uni.canvasToTempFilePath(copyArgs, this); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								const tempFilePath = await this.setFilePath(oFilePath, args) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								args.success && args.success({tempFilePath}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								resolve({tempFilePath}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							// #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							// #ifdef MP-ALIPAY 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							this.canvas.toTempFilePath(copyArgs) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							// #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						}catch(e){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							args.fail && args.fail(e) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							reject(e) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						// #ifdef MP-ALIPAY 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						if(this.ctx.toTempFilePath) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							// 钉钉 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							const ctx = uni.createCanvasContext(canvasId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							ctx.toTempFilePath(copyArgs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							my.canvasToTempFilePath(copyArgs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						// #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						// #ifndef MP-ALIPAY 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						uni.canvasToTempFilePath(copyArgs, this); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						// #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+</script> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+<style> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	.lime-painter, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	.lime-painter__canvas { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// #ifndef APP-NVUE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		width: 100%; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// #ifdef APP-NVUE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		flex: 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+</style> 
			 |