| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735 | export default{	data(){		return{			system_info:{}, //system info			canvas_width:0, //canvas width px			canvas_height:0, //canvas height px			ctx:null, //canvas object			canvas_id:null, //canvas id			hidden:true,//Whether to hide canvas			scale:1,//canvas scale			r_canvas_scale:1,			if_ctx:true		}	},	methods:{		/**		 * save r-canvas.vue object		 * @param {Object} that		 */		// saveThis(that){		// 	rCanvasThis = that		// },		/**		 * Draw round rect text		 * @param {Object} config		 * @param {Number} config.x x坐标		 * @param {Number} config.y y坐标		 * @param {Number} config.w 宽度		 * @param {Number} config.h 高度		 * @param {Number} config.radius 圆角弧度		 * @param {String} config.fill_color 矩形颜色		 */		fillRoundRect(config) {			return new Promise((resolve,reject)=>{				let x = this.compatibilitySize(parseFloat(config.x)*this.scale)				let y = this.compatibilitySize(parseFloat(config.y)*this.scale)				let w = this.compatibilitySize(parseFloat(config.w)*this.scale)				let h = this.compatibilitySize(parseFloat(config.h)*this.scale)				let radius = config.radius?parseFloat(config.radius)*this.scale:10*this.scale								let fill_color = config.fill_color || "black"				// The diameter of the circle must be less than the width and height of the rectangle				if (2 * radius > w || 2 * radius > h) { 					reject("The diameter of the circle must be less than the width and height of the rectangle")					return false; 				}				this.ctx.save();				this.ctx.translate(x, y);				//  				this.drawRoundRectPath({					w: w, 					h: h, 					radius: radius				});				this.ctx.fillStyle = fill_color				this.ctx.fill();				this.ctx.restore();				resolve()			})		},		/**		 * Draws the sides of a rounded rectangle		 * @param {Object} config		 * @param {Number} config.w 宽度		 * @param {Number} config.h 高度		 * @param {Number} config.radius 圆角弧度		 */		drawRoundRectPath(config) {			this.ctx.beginPath(0);			this.ctx.arc(config.w - config.radius, config.h - config.radius, config.radius, 0, Math.PI / 2);			this.ctx.lineTo(config.radius, config.h);			this.ctx.arc(config.radius, config.h - config.radius, config.radius, Math.PI / 2, Math.PI);			this.ctx.lineTo(0, config.radius);			this.ctx.arc(config.radius, config.radius, config.radius, Math.PI, Math.PI * 3 / 2);			this.ctx.lineTo(config.w - config.radius, 0);			this.ctx.arc(config.w - config.radius, config.radius, config.radius, Math.PI * 3 / 2, Math.PI * 2);			this.ctx.lineTo(config.w, config.h - config.radius);			this.ctx.closePath();		},		/**		 * Draw special Text,line wrapping is not supported		 * @param {Object} config		 * @param {String} config.text 文字		 * @param {Number} config.x x坐标		 * @param {Number} config.y y坐标		 * @param {String} config.font_color 文字颜色		 * @param {String} config.font_family 文字字体		 * @param {Number} config.font_size 文字大小(px)		 */		drawSpecialText(params){			let general = params.general			let list = params.list			return new Promise(async (resolve,reject)=>{				if(!general){					reject("general cannot be empty:101")					return;				}else if(list && list.length>0){					for(let i in list){						if(i != 0){							let font_size = list[i-1].font_size?parseFloat(list[i-1].font_size):20							this.ctx.setFontSize(font_size)							general.x = parseFloat(general.x) + this.ctx.measureText(list[i-1].text).width						}						list[i].x = general.x						list[i].y = general.y + (list[i].margin_top?parseFloat(list[i].margin_top):0)						await this.drawText(list[i])					}					resolve()				}else{					reject("The length of config arr is less than 0")					return;				}							})		},		/**		 * array delete empty		 * @param {Object} arr		 */		arrDeleteEmpty(arr){			let newArr = []			for(let i in arr){				if(arr[i]){					newArr.push(arr[i])				}			}			return newArr		},		/**		 * Draw Text,support line		 * @param {Object} config		 * @param {String} config.text 文字		 * @param {Number} config.max_width 文字最大宽度(大于宽度自动换行)		 * @param {Number} config.line_height 文字上下行间距		 * @param {Number} config.x x坐标		 * @param {Number} config.y y坐标		 * @param {String} config.font_color 文字颜色		 * @param {String} config.font_family 文字字体 默认值:Arial		 * @param {String} config.text_align 文字对齐方式(left/center/right)		 * @param {Number} config.font_size 文字大小(px)		 * @param {Boolean} config.line_through_height 中划线大小		 * @param {Boolean} config.line_through_color 中划线颜色		 * @param {String} config.font_style 规定文字样式		 * @param {String} config.font_variant 规定字体变体		 * @param {String} config.font_weight 规定字体粗细		 * @param {String} config.line_through_cap 线末端类型		 * @param {String} config.line_clamp 最大行数		 * @param {String} config.line_clamp_hint 超过line_clamp后,尾部显示的自定义标识 如 ...		 * @param {String} config.is_line_break 是否开启换行符换行		 * 		 */		drawText(config,configuration = {}){						configuration['line_num'] = configuration.line_num?configuration.line_num:0			configuration['text_width'] = configuration.text_width?configuration.text_width:0						return new Promise(async (resolve,reject)=>{								if(config.text){										let draw_width = 0,draw_height = 0,draw_x = config.x,draw_y = config.y					let font_size = config.font_size?(parseFloat(config.font_size)*this.scale):(20*this.scale)					let font_color = config.font_color || "#000"					let font_family = config.font_family || "Arial"					let line_height = config.line_height || config.font_size || 20					let text_align = config.text_align || "left"					let font_weight = config.font_weight || "normal"					let font_variant = config.font_variant || "normal"					let font_style = config.font_style || "normal"					let line_clamp_hint = config.line_clamp_hint || '...'					let lineBreakJoinText = ""					let max_width = config.max_width?parseFloat(config.max_width)*this.scale:0					// checkout is line break					if(config.is_line_break){						let splitTextArr = config.text.split(/[\n]/g)						if(splitTextArr && splitTextArr.length > 0){							let newSplitTextArr = this.arrDeleteEmpty(splitTextArr)							if(newSplitTextArr && newSplitTextArr.length > 0){								lineBreakJoinText = newSplitTextArr.slice(1).join("\n")								config.text = newSplitTextArr[0]							}else{								reject("Text cannot be empty:103")								return							}						}else{							reject("Text cannot be empty:102")							return						}					}										this.ctx.setFillStyle(font_color) // color					this.ctx.textAlign = text_align;					this.ctx.font = `${font_style} ${font_variant} ${font_weight} ${parseInt(font_size)}px ${font_family}`					if(configuration.text_width >= this.ctx.measureText(config.text).width){						draw_width = configuration.text_width					}else if(max_width > 0){						draw_width = max_width < this.ctx.measureText(config.text).width ? this.resetCompatibilitySize(max_width) : this.resetCompatibilitySize(this.ctx.measureText(config.text).width)					}else{						draw_width = this.ctx.measureText(config.text).width					}					configuration.text_width = draw_width / this.scale					if( max_width && this.compatibilitySize(this.ctx.measureText(config.text).width) > this.compatibilitySize(max_width)){						let current_text = ""						let text_arr = config.text.split("")						for(let i in text_arr){							if( this.compatibilitySize(this.ctx.measureText(current_text+text_arr[i]).width) > this.compatibilitySize(max_width) ){								// Hyphenation that is greater than the drawable width continues to draw								if(config.line_clamp && parseInt(config.line_clamp) == 1){									// Subtracting the current_text tail width from the line_clamp_hint width									let current_text_arr = current_text.split('')									let json_current_text = ''									while(true){										current_text_arr = current_text_arr.slice(1)										json_current_text = current_text_arr.join('')										if(this.compatibilitySize(this.ctx.measureText(json_current_text).width) <= this.compatibilitySize(this.ctx.measureText(line_clamp_hint).width)){											current_text = current_text.replace(json_current_text,'')											break;										}									}									configuration.line_num += 1									this.ctx.setFontSize(parseInt(this.compatibilitySize(font_size))) // font size									this.ctx.fillText(current_text + line_clamp_hint, this.compatibilitySize(parseFloat(config.x)*this.scale), this.compatibilitySize(parseFloat(config.y)*this.scale));								}else{									configuration.line_num += 1									this.ctx.setFontSize(parseInt(this.compatibilitySize(font_size))) // font size									this.ctx.fillText(current_text, this.compatibilitySize(parseFloat(config.x)*this.scale), this.compatibilitySize(parseFloat(config.y)*this.scale));									config.text = text_arr.slice(i).join("")									config.y = config.y + line_height									if(config.line_clamp){										config.line_clamp = parseInt(config.line_clamp) - 1									}									await this.drawText(config,configuration)								}																break;							}else{								current_text = current_text+text_arr[i]							}						}					}else{						if(config.line_through_height){							let x = parseFloat(config.x)*this.scale							let w							let y = parseFloat(config.y)*this.scale - (font_size / 2.6) 							if(text_align == "left"){								w = this.ctx.measureText(config.text).width/1.1 + parseFloat(config.x)*this.scale							}else if(text_align == "right"){								w = parseFloat(config.x)*this.scale - this.ctx.measureText(config.text).width/1.1							}else if(text_align == "center"){								x = parseFloat(config.x)*this.scale - this.ctx.measureText(config.text).width / 1.1 / 2								w = parseFloat(config.x)*this.scale + this.ctx.measureText(config.text).width / 1.1 / 2							}							this.drawLineTo({								x:x,								y:y,								w:w,								h:y,								line_width:config.line_through_height,								line_color:config.line_through_color,								line_cap:config.line_through_cap							})						}						configuration.line_num += 1						this.ctx.setFontSize(parseInt(this.compatibilitySize(font_size))) // font size						this.ctx.fillText(config.text, this.compatibilitySize(parseFloat(config.x)*this.scale), this.compatibilitySize(parseFloat(config.y)*this.scale));						if(config.line_clamp){							config.line_clamp = parseInt(config.line_clamp) - 1						}					}					if(lineBreakJoinText){						await this.drawText({...config,text:lineBreakJoinText,y:config.y + line_height},configuration)					}					draw_height = config.font_size * configuration.line_num					draw_width = configuration.text_width					resolve({draw_width,draw_height,draw_x,draw_y})				}else{					reject("Text cannot be empty:101")				}			})		},		/**		 * Draw Line		 * @param {Object} config		 * @param {Object} config.x x坐标		 * @param {Object} config.y y坐标		 * @param {Object} config.w 线的宽度		 * @param {Object} config.h 线的高度		 * @param {Object} config.line_width 线的宽度		 * @param {Object} config.line_color 线条颜色		 */		drawLineTo(config){			let x = this.compatibilitySize(config.x)			let y = this.compatibilitySize(config.y)			let w = this.compatibilitySize(config.w)			let h = this.compatibilitySize(config.h)			let line_width = config.line_width?parseFloat(config.line_width)*this.scale:1*this.scale			let line_color = config.line_color || "black"			let line_cap = config.line_cap || "butt"			this.ctx.beginPath()			this.ctx.lineCap = line_cap			this.ctx.lineWidth = line_width			this.ctx.strokeStyle = line_color			this.ctx.moveTo(x,y)			this.ctx.lineTo(w,h)			this.ctx.stroke()		},		/** 		 * Compatibility px		 * @param {Object} size		 */		compatibilitySize(size) {		  let canvasSize = (parseFloat(size) / 750) * this.system_info.windowWidth		  canvasSize = parseFloat(canvasSize * 2)		  return canvasSize		},		/**		 * Restore compatibility px		 * @param {Object} size		 */		resetCompatibilitySize(size) {		  let canvasSize = (parseFloat(size/2)/this.system_info.windowWidth) * 750		  return canvasSize		},		/**		 * Init canvas		 */		init(config){			return new Promise(async (resolve,reject)=>{				if(!config.canvas_id){					reject("Canvas ID cannot be empty, please refer to the usage example")					return;				}				this.hidden = config.hidden				this.canvas_id = config.canvas_id				let system_info = await uni.getSystemInfoSync()				this.system_info = system_info				this.scale = config.scale&&parseFloat(config.scale)>0?parseInt(config.scale):1				this.canvas_width = (config.canvas_width ? this.compatibilitySize(config.canvas_width) : system_info.windowWidth) * this.scale				this.canvas_height = (config.canvas_height ? this.compatibilitySize(config.canvas_height) : system_info.windowHeight) * this.scale,				this.r_canvas_scale = 1/this.scale				this.ctx = uni.createCanvasContext(this.canvas_id,this)				this.setCanvasConfig({					global_alpha:config.global_alpha?parseFloat(config.global_alpha):1,					backgroundColor:config.background_color?config.background_color:"transparent"				})				resolve()			})		},		/**		 * clear canvas all path		 */		clearCanvas(){			return new Promise(async (resolve,reject)=>{				if(!this.ctx){					reject("canvas is not initialized:101")					return				}else{					this.ctx.clearRect(0,0,parseFloat(this.canvas_width)*this.scale,parseFloat(this.canvas_height)*this.scale)					await this.draw()					resolve()				}			})		},		/**		 * Set canvas config		 * @param {Object} config		 */		setCanvasConfig(config){			this.ctx.globalAlpha = config.global_alpha			this.ctx.fillStyle = config.backgroundColor			this.ctx.fillRect(0, 0, parseFloat(this.canvas_width)*this.scale, parseFloat(this.canvas_height)*this.scale)		},		/**		 * set canvas width		 * @param {Object} width		 */		setCanvasWidth(width){			if(!width){				uni.showToast({					title:'setCanvasWidth:width error',					icon:'none'				})			}			this.canvas_width = this.compatibilitySize(parseFloat(width)) * this.scale			this.ctx.width = this.canvas_width		},		/**		 * set canvas height		 * @param {Object} height		 */		setCanvasHeight(height){			if(!height){				uni.showToast({					title:'setCanvasWidth:height error',					icon:'none'				})			}			this.canvas_height = this.compatibilitySize(parseFloat(height)) * this.scale			this.ctx.height = this.canvas_height		},		/**		 * Draw to filepath		 */		draw(callback){			return new Promise((resolve,reject)=>{				let stop = setTimeout(()=>{					this.ctx.draw(false,setTimeout(()=>{					    uni.canvasToTempFilePath({					    	canvasId: this.canvas_id,					    	quality: 1,					    	success: (res)=>{					    		console.log('res',res)					    		resolve(res)					    		callback && callback(res)					    	},					    	fail:(err)=>{					    		reject(JSON.stringify(err)|| "Failed to generate poster:101")					    	}					    },this)					},300))					clearTimeout(stop)				},300)			})		},		/**		 * draw rect		 * @param {Number} config.x x坐标		 * @param {Number} config.y y坐标		 * @param {Number} config.w 图形宽度(px)		 * @param {Number} config.h 图形高度(px)		 * @param {Number} config.color 图形颜色		 * @param {Number} config.is_radius 是否开启圆图(1.1.6及以下版本废弃,请使用border_radius)		 * @param {Number} config.border_width 边框大小		 * @param {Number} config.border_color 边框颜色		 * 		 */		drawRect(config){			return new Promise(async (resolve,reject)=>{				if(!config.border_width || config.border_width <=0){					config.border_width = 0				}else{					config.border_width = parseFloat(config.border_width)				}				if(parseFloat(config.border_width) > 0){					let sub_config = JSON.parse(JSON.stringify(config))					sub_config.border_width = 0					sub_config.w = config.w + config.border_width					sub_config.h = config.h + config.border_width					sub_config.color = config.border_color || 'black'					if(sub_config.border_radius){						sub_config.border_radius = parseFloat(sub_config.border_radius) + parseFloat(config.border_width) / 2					} 					await this.drawRect(sub_config)				}								let color = config.color || 'white'				config.x =  (parseFloat(config.x) + config.border_width / 2)				config.y = (parseFloat(config.y) + config.border_width / 2)				config['color'] = color				this.ctx.fillStyle = color;				if(config.is_radius || config.border_radius){					this.setNativeBorderRadius(config)					this.ctx.fill()				}else{					console.log('config.border_width',config.border_width)					this.ctx.fillRect(this.compatibilitySize(config.x*this.scale),this.compatibilitySize(config.y*this.scale),this.compatibilitySize(parseFloat(config.w)*this.scale),this.compatibilitySize(parseFloat(config.h)*this.scale))				}				resolve()			})		},		/**		 * Draw image		 * @param {Object} config		 * @param {String} config.url 图片链接		 * @param {Number} config.x x坐标		 * @param {Number} config.y y坐标		 * @param {Number} config.w 图片宽度(px)		 * @param {Number} config.h 图片高度(px)		 * @param {Number} config.border_width 边大小		 * @param {Number} config.border_color 边颜色		 * @param {Number} config.is_radius 是否开启圆图(1.1.6及以下版本废弃,请使用border_radius)		 * @param {Number} config.border_radius 圆角弧度		 */		drawImage(config){			return new Promise(async (resolve,reject)=>{				if(config.url){					let type = 0 // 1、network image  2、native image  3、base64 image					let image_url					let reg = /^https?/ig;					if(reg.test(config.url)){						type = 1					}else{						if((config.url.indexOf("data:image/png;base64") != -1) || config.url.indexOf("data:image/jpeg;base64") != -1 || config.url.indexOf("data:image/gif;base64") != -1){							type = 3						}else{							type = 2						}					}					if(type == 1){						// network image						await this.downLoadNetworkFile(config.url).then(res=>{ // two function							image_url = res						}).catch(err=>{							reject(err)							return;						})					}else if(type == 2){						// native image						const imageInfoResult = await uni.getImageInfo({							src: config.url						});						try{							if(imageInfoResult.length <= 1){								reject(imageInfoResult[0].errMsg + ':404')								return							}						}catch(e){							reject(e+':500')							return						}						let base64 = await this.urlToBase64({url:imageInfoResult[1].path})						// #ifdef MP-WEIXIN						await this.base64ToNative({url:base64}).then(res=>{							image_url = res						}).catch(err=>{							reject(JSON.stringify(err)+":501")							return;						})						// #endif						// #ifndef MP-WEIXIN						image_url = base64						// #endif											}else if(type == 3){						// #ifdef MP-WEIXIN						await this.base64ToNative({url:config.url}).then(res=>{							image_url = res						}).catch(err=>{							reject(JSON.stringify(err)+":500")							return;						})						// #endif						// #ifndef MP-WEIXIN						image_url = config.url						// #endif					}else{						reject("Other Type Errors:101")						return					}					if(config.border_width){						let border_radius = 0						if(config.border_radius){							let multiple = config.w / config.border_radius							border_radius = (parseFloat(config.w) + parseFloat(config.border_width)) / multiple						}						// drawRect						await this.drawRect({							x:parseFloat(config.x) - parseFloat(config.border_width)/2,							y:parseFloat(config.y) - parseFloat(config.border_width)/2,							w:parseFloat(config.w) + parseFloat(config.border_width),							h:parseFloat(config.h) + parseFloat(config.border_width),							color:config.border_color,							border_radius:border_radius,							border_width:config.border_width,							is_radius:config.is_radius						})					}															if(config.border_radius){						config.color =  config.color?config.color:'rgba(0,0,0,0)'												// 圆角有白边,+0.5的误差						config.w = config.w + 0.3						config.h = config.h + 0.3												this.setNativeBorderRadius(config)					}else if(config.is_radius){						//已废弃 is_radius						this.ctx.setStrokeStyle("rgba(0,0,0,0)")						this.ctx.save()						this.ctx.beginPath()						this.ctx.arc(this.compatibilitySize(parseFloat(config.x)*this.scale+parseFloat(config.w)*this.scale/2), this.compatibilitySize(parseFloat(config.y)*this.scale+parseFloat(config.h)*this.scale/2), this.compatibilitySize(parseFloat(config.w)*this.scale/2), 0, 2 * Math.PI, false)						this.ctx.stroke();						this.ctx.clip()					}										await this.ctx.drawImage(image_url,this.compatibilitySize(parseFloat(config.x)*this.scale),this.compatibilitySize(parseFloat(config.y)*this.scale),this.compatibilitySize(parseFloat(config.w)*this.scale),this.compatibilitySize(parseFloat(config.h)*this.scale))					this.ctx.restore() //Restore previously saved drawing context					resolve()				}else{					let err_msg = "Links cannot be empty:101"					reject(err_msg)				}			})		},		/**		 * base64 to native available path		 * @param {Object} config		 */		base64ToNative(config){			return new Promise((resolve,reject)=>{				let fileName = new Date().getTime()				var filePath = `${wx.env.USER_DATA_PATH}/${fileName}_rCanvas.png`				wx.getFileSystemManager().writeFile({					filePath: filePath,					data: config.url.replace(/^data:\S+\/\S+;base64,/, ''),					encoding: 'base64',					success: function() {						resolve(filePath)					},					fail: function(error) {						reject(error)					}				})			})		},		/**		 * native url to base64		 * @param {Object} config		 */		urlToBase64(config){			return new Promise(async (resolve,reject)=>{				if (typeof window != 'undefined') {					await this.downLoadNetworkFile(config.url).then(res=>{ // two function						resolve(res)					}).catch(err=>{						reject(err)					})				}else if (typeof plus != 'undefined') {					plus.io.resolveLocalFileSystemURL(config.url,(obj)=>{						obj.file((file)=>{							let fileReader = new plus.io.FileReader()							fileReader.onload = (res)=>{								resolve(res.target.result)							}							fileReader.onerror = (err)=>{								reject(err)							}							fileReader.readAsDataURL(file)						}, (err)=>{							reject(err)						})					},(err)=>{						reject(err)					})				}else if(typeof wx != 'undefined'){					wx.getFileSystemManager().readFile({						filePath: config.url,						encoding: 'base64',						success: function(res) {							resolve('data:image/png;base64,' + res.data)						},						fail: function(error) {							reject(error)						}					})				}			})		},		setNativeBorderRadius(config){			let border_radius = config.border_radius?(parseFloat(config.border_radius)*this.scale):(20*this.scale)			if ((parseFloat(config.w)*this.scale) < 2 * border_radius) border_radius = (parseFloat(config.w)*this.scale) / 2;			if ((parseFloat(config.h)*this.scale) < 2 * border_radius) border_radius = (parseFloat(config.h)*this.scale) / 2;			this.ctx.beginPath();			this.ctx.moveTo(this.compatibilitySize((parseFloat(config.x)*this.scale) + border_radius), this.compatibilitySize((parseFloat(config.y)*this.scale)));			this.ctx.arcTo(this.compatibilitySize((parseFloat(config.x)*this.scale) + (parseFloat(config.w)*this.scale)), this.compatibilitySize((parseFloat(config.y)*this.scale)), this.compatibilitySize((parseFloat(config.x)*this.scale) + (parseFloat(config.w)*this.scale)), this.compatibilitySize((parseFloat(config.y)*this.scale) + (parseFloat(config.h)*this.scale)), this.compatibilitySize(border_radius));			this.ctx.arcTo(this.compatibilitySize((parseFloat(config.x)*this.scale) + (parseFloat(config.w)*this.scale)), this.compatibilitySize((parseFloat(config.y)*this.scale) + (parseFloat(config.h)*this.scale)), this.compatibilitySize((parseFloat(config.x)*this.scale)), this.compatibilitySize((parseFloat(config.y)*this.scale) + (parseFloat(config.h)*this.scale)), this.compatibilitySize(border_radius));			this.ctx.arcTo((this.compatibilitySize(parseFloat(config.x)*this.scale)), this.compatibilitySize((parseFloat(config.y)*this.scale) + (parseFloat(config.h)*this.scale)), this.compatibilitySize((parseFloat(config.x)*this.scale)), this.compatibilitySize((parseFloat(config.y)*this.scale)), this.compatibilitySize(border_radius));			this.ctx.arcTo(this.compatibilitySize((parseFloat(config.x)*this.scale)), this.compatibilitySize((parseFloat(config.y)*this.scale)), this.compatibilitySize((parseFloat(config.x)*this.scale) + (parseFloat(config.w)*this.scale)), this.compatibilitySize((parseFloat(config.y)*this.scale)), this.compatibilitySize(border_radius));			this.ctx.closePath();			this.ctx.strokeStyle = config.color || config.border_color || 'rgba(0,0,0,0)'; // 设置绘制边框的颜色			this.ctx.stroke();			this.ctx.save()			this.ctx.clip();					},		/**		 * Download network file		 * @param {Object} url : download url		 */		downLoadNetworkFile(url){			return new Promise((resolve,reject)=>{				uni.downloadFile({					url,					success:(res)=>{						if(res.statusCode == 200){							resolve(res.tempFilePath)						}else{							reject("Download Image Fail:102")						}					},					fail:(err)=>{						reject("Download Image Fail:101")					}				})			})		},		/**		 * Save image to natice		 * @param {Object} filePath : native imageUrl		 */		saveImage(filePath){			return new Promise((resolve,reject)=>{				if(!filePath){					reject("FilePath cannot be null:101")					return;				}								// #ifdef H5					var createA = document.createElement("a");					createA.download = filePath;					createA.href = filePath;					document.body.appendChild(createA);					createA.click();					createA.remove();					resolve()				// #endif								// #ifndef H5				uni.saveImageToPhotosAlbum({					filePath: filePath,					success:(res)=>{						resolve(res)					}, 					fail:(err)=>{						reject(err)					}				})				// #endif			})		}	}}
 |