1266 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
		
		
			
		
	
	
			1266 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
|  | /** | |||
|  |  * we-cropper v1.3.9 | |||
|  |  * (c) 2020 dlhandsome | |||
|  |  * @license MIT | |||
|  |  */ | |||
|  | (function(global, factory) { | |||
|  | 	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : | |||
|  | 		typeof define === 'function' && define.amd ? define(factory) : | |||
|  | 		(global.WeCropper = factory()); | |||
|  | }(this, (function() { | |||
|  | 	'use strict'; | |||
|  | 
 | |||
|  | 	var device = void 0; | |||
|  | 	var TOUCH_STATE = ['touchstarted', 'touchmoved', 'touchended']; | |||
|  | 
 | |||
|  | 	function firstLetterUpper(str) { | |||
|  | 		return str.charAt(0).toUpperCase() + str.slice(1) | |||
|  | 	} | |||
|  | 
 | |||
|  | 	function setTouchState(instance) { | |||
|  | 		var arg = [], | |||
|  | 			len = arguments.length - 1; | |||
|  | 		while (len-- > 0) arg[len] = arguments[len + 1]; | |||
|  | 
 | |||
|  | 		TOUCH_STATE.forEach(function(key, i) { | |||
|  | 			if (arg[i] !== undefined) { | |||
|  | 				instance[key] = arg[i]; | |||
|  | 			} | |||
|  | 		}); | |||
|  | 	} | |||
|  | 
 | |||
|  | 	function validator(instance, o) { | |||
|  | 		Object.defineProperties(instance, o); | |||
|  | 	} | |||
|  | 
 | |||
|  | 	function getDevice() { | |||
|  | 		if (!device) { | |||
|  | 			device = uni.getSystemInfoSync(); | |||
|  | 		} | |||
|  | 		return device | |||
|  | 	} | |||
|  | 
 | |||
|  | 	var tmp = {}; | |||
|  | 
 | |||
|  | 	var ref = getDevice(); | |||
|  | 	var pixelRatio = ref.pixelRatio; | |||
|  | 
 | |||
|  | 	var DEFAULT = { | |||
|  | 		id: { | |||
|  | 			default: 'cropper', | |||
|  | 			get: function get() { | |||
|  | 				return tmp.id | |||
|  | 			}, | |||
|  | 			set: function set(value) { | |||
|  | 				if (typeof(value) !== 'string') { | |||
|  | 					console.error(("id:" + value + " is invalid")); | |||
|  | 				} | |||
|  | 				tmp.id = value; | |||
|  | 			} | |||
|  | 		}, | |||
|  | 		width: { | |||
|  | 			default: 750, | |||
|  | 			get: function get() { | |||
|  | 				return tmp.width | |||
|  | 			}, | |||
|  | 			set: function set(value) { | |||
|  | 				if (typeof(value) !== 'number') { | |||
|  | 					console.error(("width:" + value + " is invalid")); | |||
|  | 				} | |||
|  | 				tmp.width = value; | |||
|  | 			} | |||
|  | 		}, | |||
|  | 		height: { | |||
|  | 			default: 750, | |||
|  | 			get: function get() { | |||
|  | 				return tmp.height | |||
|  | 			}, | |||
|  | 			set: function set(value) { | |||
|  | 				if (typeof(value) !== 'number') { | |||
|  | 					console.error(("height:" + value + " is invalid")); | |||
|  | 				} | |||
|  | 				tmp.height = value; | |||
|  | 			} | |||
|  | 		}, | |||
|  | 		pixelRatio: { | |||
|  | 			default: pixelRatio, | |||
|  | 			get: function get() { | |||
|  | 				return tmp.pixelRatio | |||
|  | 			}, | |||
|  | 			set: function set(value) { | |||
|  | 				if (typeof(value) !== 'number') { | |||
|  | 					console.error(("pixelRatio:" + value + " is invalid")); | |||
|  | 				} | |||
|  | 				tmp.pixelRatio = value; | |||
|  | 			} | |||
|  | 		}, | |||
|  | 		scale: { | |||
|  | 			default: 2.5, | |||
|  | 			get: function get() { | |||
|  | 				return tmp.scale | |||
|  | 			}, | |||
|  | 			set: function set(value) { | |||
|  | 				if (typeof(value) !== 'number') { | |||
|  | 					console.error(("scale:" + value + " is invalid")); | |||
|  | 				} | |||
|  | 				tmp.scale = value; | |||
|  | 			} | |||
|  | 		}, | |||
|  | 		zoom: { | |||
|  | 			default: 5, | |||
|  | 			get: function get() { | |||
|  | 				return tmp.zoom | |||
|  | 			}, | |||
|  | 			set: function set(value) { | |||
|  | 				if (typeof(value) !== 'number') { | |||
|  | 					console.error(("zoom:" + value + " is invalid")); | |||
|  | 				} else if (value < 0 || value > 10) { | |||
|  | 					console.error("zoom should be ranged in 0 ~ 10"); | |||
|  | 				} | |||
|  | 				tmp.zoom = value; | |||
|  | 			} | |||
|  | 		}, | |||
|  | 		src: { | |||
|  | 			default: '', | |||
|  | 			get: function get() { | |||
|  | 				return tmp.src | |||
|  | 			}, | |||
|  | 			set: function set(value) { | |||
|  | 				if (typeof(value) !== 'string') { | |||
|  | 					console.error(("src:" + value + " is invalid")); | |||
|  | 				} | |||
|  | 				tmp.src = value; | |||
|  | 			} | |||
|  | 		}, | |||
|  | 		cut: { | |||
|  | 			default: {}, | |||
|  | 			get: function get() { | |||
|  | 				return tmp.cut | |||
|  | 			}, | |||
|  | 			set: function set(value) { | |||
|  | 				if (typeof(value) !== 'object') { | |||
|  | 					console.error(("cut:" + value + " is invalid")); | |||
|  | 				} | |||
|  | 				tmp.cut = value; | |||
|  | 			} | |||
|  | 		}, | |||
|  | 		boundStyle: { | |||
|  | 			default: {}, | |||
|  | 			get: function get() { | |||
|  | 				return tmp.boundStyle | |||
|  | 			}, | |||
|  | 			set: function set(value) { | |||
|  | 				if (typeof(value) !== 'object') { | |||
|  | 					console.error(("boundStyle:" + value + " is invalid")); | |||
|  | 				} | |||
|  | 				tmp.boundStyle = value; | |||
|  | 			} | |||
|  | 		}, | |||
|  | 		onReady: { | |||
|  | 			default: null, | |||
|  | 			get: function get() { | |||
|  | 				return tmp.ready | |||
|  | 			}, | |||
|  | 			set: function set(value) { | |||
|  | 				tmp.ready = value; | |||
|  | 			} | |||
|  | 		}, | |||
|  | 		onBeforeImageLoad: { | |||
|  | 			default: null, | |||
|  | 			get: function get() { | |||
|  | 				return tmp.beforeImageLoad | |||
|  | 			}, | |||
|  | 			set: function set(value) { | |||
|  | 				tmp.beforeImageLoad = value; | |||
|  | 			} | |||
|  | 		}, | |||
|  | 		onImageLoad: { | |||
|  | 			default: null, | |||
|  | 			get: function get() { | |||
|  | 				return tmp.imageLoad | |||
|  | 			}, | |||
|  | 			set: function set(value) { | |||
|  | 				tmp.imageLoad = value; | |||
|  | 			} | |||
|  | 		}, | |||
|  | 		onBeforeDraw: { | |||
|  | 			default: null, | |||
|  | 			get: function get() { | |||
|  | 				return tmp.beforeDraw | |||
|  | 			}, | |||
|  | 			set: function set(value) { | |||
|  | 				tmp.beforeDraw = value; | |||
|  | 			} | |||
|  | 		} | |||
|  | 	}; | |||
|  | 
 | |||
|  | 	var ref$1 = getDevice(); | |||
|  | 	var windowWidth = ref$1.windowWidth; | |||
|  | 
 | |||
|  | 	function prepare() { | |||
|  | 		var self = this; | |||
|  | 
 | |||
|  | 		// v1.4.0 版本中将不再自动绑定we-cropper实例
 | |||
|  | 		self.attachPage = function() { | |||
|  | 			var pages = getCurrentPages(); | |||
|  | 			// 获取到当前page上下文
 | |||
|  | 			var pageContext = pages[pages.length - 1]; | |||
|  | 			// 把this依附在Page上下文的wecropper属性上,便于在page钩子函数中访问
 | |||
|  | 			Object.defineProperty(pageContext, 'wecropper', { | |||
|  | 				get: function get() { | |||
|  | 					console.warn( | |||
|  | 						'Instance will not be automatically bound to the page after v1.4.0\n\n' + | |||
|  | 						'Please use a custom instance name instead\n\n' + | |||
|  | 						'Example: \n' + | |||
|  | 						'this.mycropper = new WeCropper(options)\n\n' + | |||
|  | 						'// ...\n' + | |||
|  | 						'this.mycropper.getCropperImage()' | |||
|  | 					); | |||
|  | 					return self | |||
|  | 				}, | |||
|  | 				configurable: true | |||
|  | 			}); | |||
|  | 		}; | |||
|  | 
 | |||
|  | 		self.createCtx = function() { | |||
|  | 			var id = self.id; | |||
|  | 			var targetId = self.targetId; | |||
|  | 
 | |||
|  | 			if (id) { | |||
|  | 				self.ctx = self.ctx || uni.createCanvasContext(id); | |||
|  | 				self.targetCtx = self.targetCtx || uni.createCanvasContext(targetId); | |||
|  | 			} else { | |||
|  | 				console.error("constructor: create canvas context failed, 'id' must be valuable"); | |||
|  | 			} | |||
|  | 		}; | |||
|  | 
 | |||
|  | 		self.deviceRadio = windowWidth / 750; | |||
|  | 	} | |||
|  | 
 | |||
|  | 	var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== | |||
|  | 		'undefined' ? self : {}; | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 	function createCommonjsModule(fn, module) { | |||
|  | 		return module = { | |||
|  | 			exports: {} | |||
|  | 		}, fn(module, module.exports), module.exports; | |||
|  | 	} | |||
|  | 
 | |||
|  | 	var tools = createCommonjsModule(function(module, exports) { | |||
|  | 		/** | |||
|  | 		 * String type check | |||
|  | 		 */ | |||
|  | 		exports.isStr = function(v) { | |||
|  | 			return typeof v === 'string'; | |||
|  | 		}; | |||
|  | 		/** | |||
|  | 		 * Number type check | |||
|  | 		 */ | |||
|  | 		exports.isNum = function(v) { | |||
|  | 			return typeof v === 'number'; | |||
|  | 		}; | |||
|  | 		/** | |||
|  | 		 * Array type check | |||
|  | 		 */ | |||
|  | 		exports.isArr = Array.isArray; | |||
|  | 		/** | |||
|  | 		 * undefined type check | |||
|  | 		 */ | |||
|  | 		exports.isUndef = function(v) { | |||
|  | 			return v === undefined; | |||
|  | 		}; | |||
|  | 
 | |||
|  | 		exports.isTrue = function(v) { | |||
|  | 			return v === true; | |||
|  | 		}; | |||
|  | 
 | |||
|  | 		exports.isFalse = function(v) { | |||
|  | 			return v === false; | |||
|  | 		}; | |||
|  | 		/** | |||
|  | 		 * Function type check | |||
|  | 		 */ | |||
|  | 		exports.isFunc = function(v) { | |||
|  | 			return typeof v === 'function'; | |||
|  | 		}; | |||
|  | 		/** | |||
|  | 		 * Quick object check - this is primarily used to tell | |||
|  | 		 * Objects from primitive values when we know the value | |||
|  | 		 * is a JSON-compliant type. | |||
|  | 		 */ | |||
|  | 		exports.isObj = exports.isObject = function(obj) { | |||
|  | 			return obj !== null && typeof obj === 'object' | |||
|  | 		}; | |||
|  | 
 | |||
|  | 		/** | |||
|  | 		 * Strict object type check. Only returns true | |||
|  | 		 * for plain JavaScript objects. | |||
|  | 		 */ | |||
|  | 		var _toString = Object.prototype.toString; | |||
|  | 		exports.isPlainObject = function(obj) { | |||
|  | 			return _toString.call(obj) === '[object Object]' | |||
|  | 		}; | |||
|  | 
 | |||
|  | 		/** | |||
|  | 		 * Check whether the object has the property. | |||
|  | 		 */ | |||
|  | 		var hasOwnProperty = Object.prototype.hasOwnProperty; | |||
|  | 		exports.hasOwn = function(obj, key) { | |||
|  | 			return hasOwnProperty.call(obj, key) | |||
|  | 		}; | |||
|  | 
 | |||
|  | 		/** | |||
|  | 		 * Perform no operation. | |||
|  | 		 * Stubbing args to make Flow happy without leaving useless transpiled code | |||
|  | 		 * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/)
 | |||
|  | 		 */ | |||
|  | 		exports.noop = function(a, b, c) {}; | |||
|  | 
 | |||
|  | 		/** | |||
|  | 		 * Check if val is a valid array index. | |||
|  | 		 */ | |||
|  | 		exports.isValidArrayIndex = function(val) { | |||
|  | 			var n = parseFloat(String(val)); | |||
|  | 			return n >= 0 && Math.floor(n) === n && isFinite(val) | |||
|  | 		}; | |||
|  | 	}); | |||
|  | 
 | |||
|  | 	var tools_7 = tools.isFunc; | |||
|  | 	var tools_10 = tools.isPlainObject; | |||
|  | 
 | |||
|  | 	var EVENT_TYPE = ['ready', 'beforeImageLoad', 'beforeDraw', 'imageLoad']; | |||
|  | 
 | |||
|  | 	function observer() { | |||
|  | 		var self = this; | |||
|  | 
 | |||
|  | 		self.on = function(event, fn) { | |||
|  | 			if (EVENT_TYPE.indexOf(event) > -1) { | |||
|  | 				if (tools_7(fn)) { | |||
|  | 					event === 'ready' ? | |||
|  | 						fn(self) : | |||
|  | 						self[("on" + (firstLetterUpper(event)))] = fn; | |||
|  | 				} | |||
|  | 			} else { | |||
|  | 				console.error(("event: " + event + " is invalid")); | |||
|  | 			} | |||
|  | 			return self | |||
|  | 		}; | |||
|  | 	} | |||
|  | 
 | |||
|  | 	function wxPromise(fn) { | |||
|  | 		return function(obj) { | |||
|  | 			var args = [], | |||
|  | 				len = arguments.length - 1; | |||
|  | 			while (len-- > 0) args[len] = arguments[len + 1]; | |||
|  | 
 | |||
|  | 			if (obj === void 0) obj = {}; | |||
|  | 			return new Promise(function(resolve, reject) { | |||
|  | 				obj.success = function(res) { | |||
|  | 					resolve(res); | |||
|  | 				}; | |||
|  | 				obj.fail = function(err) { | |||
|  | 					reject(err); | |||
|  | 				}; | |||
|  | 				fn.apply(void 0, [obj].concat(args)); | |||
|  | 			}) | |||
|  | 		} | |||
|  | 	} | |||
|  | 
 | |||
|  | 	function draw(ctx, reserve) { | |||
|  | 		if (reserve === void 0) reserve = false; | |||
|  | 
 | |||
|  | 		return new Promise(function(resolve) { | |||
|  | 			ctx.draw(reserve, resolve); | |||
|  | 		}) | |||
|  | 	} | |||
|  | 
 | |||
|  | 	var getImageInfo = wxPromise(uni.getImageInfo); | |||
|  | 
 | |||
|  | 	var canvasToTempFilePath = wxPromise(uni.canvasToTempFilePath); | |||
|  | 
 | |||
|  | 	var base64 = createCommonjsModule(function(module, exports) { | |||
|  | 		/*! http://mths.be/base64 v0.1.0 by @mathias | MIT license */ | |||
|  | 		(function(root) { | |||
|  | 
 | |||
|  | 			// Detect free variables `exports`.
 | |||
|  | 			var freeExports = 'object' == 'object' && exports; | |||
|  | 
 | |||
|  | 			// Detect free variable `module`.
 | |||
|  | 			var freeModule = 'object' == 'object' && module && | |||
|  | 				module.exports == freeExports && module; | |||
|  | 
 | |||
|  | 			// Detect free variable `global`, from Node.js or Browserified code, and use
 | |||
|  | 			// it as `root`.
 | |||
|  | 			var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal; | |||
|  | 			if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) { | |||
|  | 				root = freeGlobal; | |||
|  | 			} | |||
|  | 
 | |||
|  | 			/*--------------------------------------------------------------------------*/ | |||
|  | 
 | |||
|  | 			var InvalidCharacterError = function(message) { | |||
|  | 				this.message = message; | |||
|  | 			}; | |||
|  | 			InvalidCharacterError.prototype = new Error; | |||
|  | 			InvalidCharacterError.prototype.name = 'InvalidCharacterError'; | |||
|  | 
 | |||
|  | 			var error = function(message) { | |||
|  | 				// Note: the error messages used throughout this file match those used by
 | |||
|  | 				// the native `atob`/`btoa` implementation in Chromium.
 | |||
|  | 				throw new InvalidCharacterError(message); | |||
|  | 			}; | |||
|  | 
 | |||
|  | 			var TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; | |||
|  | 			// http://whatwg.org/html/common-microsyntaxes.html#space-character
 | |||
|  | 			var REGEX_SPACE_CHARACTERS = /[\t\n\f\r ]/g; | |||
|  | 
 | |||
|  | 			// `decode` is designed to be fully compatible with `atob` as described in the
 | |||
|  | 			// HTML Standard. http://whatwg.org/html/webappapis.html#dom-windowbase64-atob
 | |||
|  | 			// The optimized base64-decoding algorithm used is based on @atk’s excellent
 | |||
|  | 			// implementation. https://gist.github.com/atk/1020396
 | |||
|  | 			var decode = function(input) { | |||
|  | 				input = String(input) | |||
|  | 					.replace(REGEX_SPACE_CHARACTERS, ''); | |||
|  | 				var length = input.length; | |||
|  | 				if (length % 4 == 0) { | |||
|  | 					input = input.replace(/==?$/, ''); | |||
|  | 					length = input.length; | |||
|  | 				} | |||
|  | 				if ( | |||
|  | 					length % 4 == 1 || | |||
|  | 					// http://whatwg.org/C#alphanumeric-ascii-characters
 | |||
|  | 					/[^+a-zA-Z0-9/]/.test(input) | |||
|  | 				) { | |||
|  | 					error( | |||
|  | 						'Invalid character: the string to be decoded is not correctly encoded.' | |||
|  | 					); | |||
|  | 				} | |||
|  | 				var bitCounter = 0; | |||
|  | 				var bitStorage; | |||
|  | 				var buffer; | |||
|  | 				var output = ''; | |||
|  | 				var position = -1; | |||
|  | 				while (++position < length) { | |||
|  | 					buffer = TABLE.indexOf(input.charAt(position)); | |||
|  | 					bitStorage = bitCounter % 4 ? bitStorage * 64 + buffer : buffer; | |||
|  | 					// Unless this is the first of a group of 4 characters…
 | |||
|  | 					if (bitCounter++ % 4) { | |||
|  | 						// …convert the first 8 bits to a single ASCII character.
 | |||
|  | 						output += String.fromCharCode( | |||
|  | 							0xFF & bitStorage >> (-2 * bitCounter & 6) | |||
|  | 						); | |||
|  | 					} | |||
|  | 				} | |||
|  | 				return output; | |||
|  | 			}; | |||
|  | 
 | |||
|  | 			// `encode` is designed to be fully compatible with `btoa` as described in the
 | |||
|  | 			// HTML Standard: http://whatwg.org/html/webappapis.html#dom-windowbase64-btoa
 | |||
|  | 			var encode = function(input) { | |||
|  | 				input = String(input); | |||
|  | 				if (/[^\0-\xFF]/.test(input)) { | |||
|  | 					// Note: no need to special-case astral symbols here, as surrogates are
 | |||
|  | 					// matched, and the input is supposed to only contain ASCII anyway.
 | |||
|  | 					error( | |||
|  | 						'The string to be encoded contains characters outside of the ' + | |||
|  | 						'Latin1 range.' | |||
|  | 					); | |||
|  | 				} | |||
|  | 				var padding = input.length % 3; | |||
|  | 				var output = ''; | |||
|  | 				var position = -1; | |||
|  | 				var a; | |||
|  | 				var b; | |||
|  | 				var c; | |||
|  | 				var buffer; | |||
|  | 				// Make sure any padding is handled outside of the loop.
 | |||
|  | 				var length = input.length - padding; | |||
|  | 
 | |||
|  | 				while (++position < length) { | |||
|  | 					// Read three bytes, i.e. 24 bits.
 | |||
|  | 					a = input.charCodeAt(position) << 16; | |||
|  | 					b = input.charCodeAt(++position) << 8; | |||
|  | 					c = input.charCodeAt(++position); | |||
|  | 					buffer = a + b + c; | |||
|  | 					// Turn the 24 bits into four chunks of 6 bits each, and append the
 | |||
|  | 					// matching character for each of them to the output.
 | |||
|  | 					output += ( | |||
|  | 						TABLE.charAt(buffer >> 18 & 0x3F) + | |||
|  | 						TABLE.charAt(buffer >> 12 & 0x3F) + | |||
|  | 						TABLE.charAt(buffer >> 6 & 0x3F) + | |||
|  | 						TABLE.charAt(buffer & 0x3F) | |||
|  | 					); | |||
|  | 				} | |||
|  | 
 | |||
|  | 				if (padding == 2) { | |||
|  | 					a = input.charCodeAt(position) << 8; | |||
|  | 					b = input.charCodeAt(++position); | |||
|  | 					buffer = a + b; | |||
|  | 					output += ( | |||
|  | 						TABLE.charAt(buffer >> 10) + | |||
|  | 						TABLE.charAt((buffer >> 4) & 0x3F) + | |||
|  | 						TABLE.charAt((buffer << 2) & 0x3F) + | |||
|  | 						'=' | |||
|  | 					); | |||
|  | 				} else if (padding == 1) { | |||
|  | 					buffer = input.charCodeAt(position); | |||
|  | 					output += ( | |||
|  | 						TABLE.charAt(buffer >> 2) + | |||
|  | 						TABLE.charAt((buffer << 4) & 0x3F) + | |||
|  | 						'==' | |||
|  | 					); | |||
|  | 				} | |||
|  | 
 | |||
|  | 				return output; | |||
|  | 			}; | |||
|  | 
 | |||
|  | 			var base64 = { | |||
|  | 				'encode': encode, | |||
|  | 				'decode': decode, | |||
|  | 				'version': '0.1.0' | |||
|  | 			}; | |||
|  | 
 | |||
|  | 			// Some AMD build optimizers, like r.js, check for specific condition patterns
 | |||
|  | 			// like the following:
 | |||
|  | 			if ( | |||
|  | 				typeof undefined == 'function' && | |||
|  | 				typeof undefined.amd == 'object' && | |||
|  | 				undefined.amd | |||
|  | 			) { | |||
|  | 				undefined(function() { | |||
|  | 					return base64; | |||
|  | 				}); | |||
|  | 			} else if (freeExports && !freeExports.nodeType) { | |||
|  | 				if (freeModule) { // in Node.js or RingoJS v0.8.0+
 | |||
|  | 					freeModule.exports = base64; | |||
|  | 				} else { // in Narwhal or RingoJS v0.7.0-
 | |||
|  | 					for (var key in base64) { | |||
|  | 						base64.hasOwnProperty(key) && (freeExports[key] = base64[key]); | |||
|  | 					} | |||
|  | 				} | |||
|  | 			} else { // in Rhino or a web browser
 | |||
|  | 				root.base64 = base64; | |||
|  | 			} | |||
|  | 
 | |||
|  | 		}(commonjsGlobal)); | |||
|  | 	}); | |||
|  | 
 | |||
|  | 	function makeURI(strData, type) { | |||
|  | 		return 'data:' + type + ';base64,' + strData | |||
|  | 	} | |||
|  | 
 | |||
|  | 	function fixType(type) { | |||
|  | 		type = type.toLowerCase().replace(/jpg/i, 'jpeg'); | |||
|  | 		var r = type.match(/png|jpeg|bmp|gif/)[0]; | |||
|  | 		return 'image/' + r | |||
|  | 	} | |||
|  | 
 | |||
|  | 	function encodeData(data) { | |||
|  | 		var str = ''; | |||
|  | 		if (typeof data === 'string') { | |||
|  | 			str = data; | |||
|  | 		} else { | |||
|  | 			for (var i = 0; i < data.length; i++) { | |||
|  | 				str += String.fromCharCode(data[i]); | |||
|  | 			} | |||
|  | 		} | |||
|  | 		return base64.encode(str) | |||
|  | 	} | |||
|  | 
 | |||
|  | 	/** | |||
|  | 	 * 获取图像区域隐含的像素数据 | |||
|  | 	 * @param canvasId canvas标识 | |||
|  | 	 * @param x 将要被提取的图像数据矩形区域的左上角 x 坐标 | |||
|  | 	 * @param y 将要被提取的图像数据矩形区域的左上角 y 坐标 | |||
|  | 	 * @param width 将要被提取的图像数据矩形区域的宽度 | |||
|  | 	 * @param height 将要被提取的图像数据矩形区域的高度 | |||
|  | 	 * @param done 完成回调 | |||
|  | 	 */ | |||
|  | 	function getImageData(canvasId, x, y, width, height, done) { | |||
|  | 		uni.canvasGetImageData({ | |||
|  | 			canvasId: canvasId, | |||
|  | 			x: x, | |||
|  | 			y: y, | |||
|  | 			width: width, | |||
|  | 			height: height, | |||
|  | 			success: function success(res) { | |||
|  | 				done(res, null); | |||
|  | 			}, | |||
|  | 			fail: function fail(res) { | |||
|  | 				done(null, res); | |||
|  | 			} | |||
|  | 		}); | |||
|  | 	} | |||
|  | 
 | |||
|  | 	/** | |||
|  | 	 * 生成bmp格式图片 | |||
|  | 	 * 按照规则生成图片响应头和响应体 | |||
|  | 	 * @param oData 用来描述 canvas 区域隐含的像素数据 { data, width, height } = oData | |||
|  | 	 * @returns {*} base64字符串 | |||
|  | 	 */ | |||
|  | 	function genBitmapImage(oData) { | |||
|  | 		//
 | |||
|  | 		// BITMAPFILEHEADER: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183374(v=vs.85).aspx
 | |||
|  | 		// BITMAPINFOHEADER: http://msdn.microsoft.com/en-us/library/dd183376.aspx
 | |||
|  | 		//
 | |||
|  | 		var biWidth = oData.width; | |||
|  | 		var biHeight = oData.height; | |||
|  | 		var biSizeImage = biWidth * biHeight * 3; | |||
|  | 		var bfSize = biSizeImage + 54; // total header size = 54 bytes
 | |||
|  | 
 | |||
|  | 		//
 | |||
|  | 		//  typedef struct tagBITMAPFILEHEADER {
 | |||
|  | 		//  	WORD bfType;
 | |||
|  | 		//  	DWORD bfSize;
 | |||
|  | 		//  	WORD bfReserved1;
 | |||
|  | 		//  	WORD bfReserved2;
 | |||
|  | 		//  	DWORD bfOffBits;
 | |||
|  | 		//  } BITMAPFILEHEADER;
 | |||
|  | 		//
 | |||
|  | 		var BITMAPFILEHEADER = [ | |||
|  | 			// WORD bfType -- The file type signature; must be "BM"
 | |||
|  | 			0x42, 0x4D, | |||
|  | 			// DWORD bfSize -- The size, in bytes, of the bitmap file
 | |||
|  | 			bfSize & 0xff, bfSize >> 8 & 0xff, bfSize >> 16 & 0xff, bfSize >> 24 & 0xff, | |||
|  | 			// WORD bfReserved1 -- Reserved; must be zero
 | |||
|  | 			0, 0, | |||
|  | 			// WORD bfReserved2 -- Reserved; must be zero
 | |||
|  | 			0, 0, | |||
|  | 			// DWORD bfOffBits -- The offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits.
 | |||
|  | 			54, 0, 0, 0 | |||
|  | 		]; | |||
|  | 
 | |||
|  | 		//
 | |||
|  | 		//  typedef struct tagBITMAPINFOHEADER {
 | |||
|  | 		//  	DWORD biSize;
 | |||
|  | 		//  	LONG  biWidth;
 | |||
|  | 		//  	LONG  biHeight;
 | |||
|  | 		//  	WORD  biPlanes;
 | |||
|  | 		//  	WORD  biBitCount;
 | |||
|  | 		//  	DWORD biCompression;
 | |||
|  | 		//  	DWORD biSizeImage;
 | |||
|  | 		//  	LONG  biXPelsPerMeter;
 | |||
|  | 		//  	LONG  biYPelsPerMeter;
 | |||
|  | 		//  	DWORD biClrUsed;
 | |||
|  | 		//  	DWORD biClrImportant;
 | |||
|  | 		//  } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
 | |||
|  | 		//
 | |||
|  | 		var BITMAPINFOHEADER = [ | |||
|  | 			// DWORD biSize -- The number of bytes required by the structure
 | |||
|  | 			40, 0, 0, 0, | |||
|  | 			// LONG biWidth -- The width of the bitmap, in pixels
 | |||
|  | 			biWidth & 0xff, biWidth >> 8 & 0xff, biWidth >> 16 & 0xff, biWidth >> 24 & 0xff, | |||
|  | 			// LONG biHeight -- The height of the bitmap, in pixels
 | |||
|  | 			biHeight & 0xff, biHeight >> 8 & 0xff, biHeight >> 16 & 0xff, biHeight >> 24 & 0xff, | |||
|  | 			// WORD biPlanes -- The number of planes for the target device. This value must be set to 1
 | |||
|  | 			1, 0, | |||
|  | 			// WORD biBitCount -- The number of bits-per-pixel, 24 bits-per-pixel -- the bitmap
 | |||
|  | 			// has a maximum of 2^24 colors (16777216, Truecolor)
 | |||
|  | 			24, 0, | |||
|  | 			// DWORD biCompression -- The type of compression, BI_RGB (code 0) -- uncompressed
 | |||
|  | 			0, 0, 0, 0, | |||
|  | 			// DWORD biSizeImage -- The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps
 | |||
|  | 			biSizeImage & 0xff, biSizeImage >> 8 & 0xff, biSizeImage >> 16 & 0xff, biSizeImage >> 24 & 0xff, | |||
|  | 			// LONG biXPelsPerMeter, unused
 | |||
|  | 			0, 0, 0, 0, | |||
|  | 			// LONG biYPelsPerMeter, unused
 | |||
|  | 			0, 0, 0, 0, | |||
|  | 			// DWORD biClrUsed, the number of color indexes of palette, unused
 | |||
|  | 			0, 0, 0, 0, | |||
|  | 			// DWORD biClrImportant, unused
 | |||
|  | 			0, 0, 0, 0 | |||
|  | 		]; | |||
|  | 
 | |||
|  | 		var iPadding = (4 - ((biWidth * 3) % 4)) % 4; | |||
|  | 
 | |||
|  | 		var aImgData = oData.data; | |||
|  | 
 | |||
|  | 		var strPixelData = ''; | |||
|  | 		var biWidth4 = biWidth << 2; | |||
|  | 		var y = biHeight; | |||
|  | 		var fromCharCode = String.fromCharCode; | |||
|  | 
 | |||
|  | 		do { | |||
|  | 			var iOffsetY = biWidth4 * (y - 1); | |||
|  | 			var strPixelRow = ''; | |||
|  | 			for (var x = 0; x < biWidth; x++) { | |||
|  | 				var iOffsetX = x << 2; | |||
|  | 				strPixelRow += fromCharCode(aImgData[iOffsetY + iOffsetX + 2]) + | |||
|  | 					fromCharCode(aImgData[iOffsetY + iOffsetX + 1]) + | |||
|  | 					fromCharCode(aImgData[iOffsetY + iOffsetX]); | |||
|  | 			} | |||
|  | 
 | |||
|  | 			for (var c = 0; c < iPadding; c++) { | |||
|  | 				strPixelRow += String.fromCharCode(0); | |||
|  | 			} | |||
|  | 
 | |||
|  | 			strPixelData += strPixelRow; | |||
|  | 		} while (--y) | |||
|  | 
 | |||
|  | 		var strEncoded = encodeData(BITMAPFILEHEADER.concat(BITMAPINFOHEADER)) + encodeData(strPixelData); | |||
|  | 
 | |||
|  | 		return strEncoded | |||
|  | 	} | |||
|  | 
 | |||
|  | 	/** | |||
|  | 	 * 转换为图片base64 | |||
|  | 	 * @param canvasId canvas标识 | |||
|  | 	 * @param x 将要被提取的图像数据矩形区域的左上角 x 坐标 | |||
|  | 	 * @param y 将要被提取的图像数据矩形区域的左上角 y 坐标 | |||
|  | 	 * @param width 将要被提取的图像数据矩形区域的宽度 | |||
|  | 	 * @param height 将要被提取的图像数据矩形区域的高度 | |||
|  | 	 * @param type 转换图片类型 | |||
|  | 	 * @param done 完成回调 | |||
|  | 	 */ | |||
|  | 	function convertToImage(canvasId, x, y, width, height, type, done) { | |||
|  | 		if (done === void 0) done = function() {}; | |||
|  | 
 | |||
|  | 		if (type === undefined) { | |||
|  | 			type = 'png'; | |||
|  | 		} | |||
|  | 		type = fixType(type); | |||
|  | 		if (/bmp/.test(type)) { | |||
|  | 			getImageData(canvasId, x, y, width, height, function(data, err) { | |||
|  | 				var strData = genBitmapImage(data); | |||
|  | 				tools_7(done) && done(makeURI(strData, 'image/' + type), err); | |||
|  | 			}); | |||
|  | 		} else { | |||
|  | 			console.error('暂不支持生成\'' + type + '\'类型的base64图片'); | |||
|  | 		} | |||
|  | 	} | |||
|  | 
 | |||
|  | 	var CanvasToBase64 = { | |||
|  | 		convertToImage: convertToImage, | |||
|  | 		// convertToPNG: function (width, height, done) {
 | |||
|  | 		//   return convertToImage(width, height, 'png', done)
 | |||
|  | 		// },
 | |||
|  | 		// convertToJPEG: function (width, height, done) {
 | |||
|  | 		//   return convertToImage(width, height, 'jpeg', done)
 | |||
|  | 		// },
 | |||
|  | 		// convertToGIF: function (width, height, done) {
 | |||
|  | 		//   return convertToImage(width, height, 'gif', done)
 | |||
|  | 		// },
 | |||
|  | 		convertToBMP: function(ref, done) { | |||
|  | 			if (ref === void 0) ref = {}; | |||
|  | 			var canvasId = ref.canvasId; | |||
|  | 			var x = ref.x; | |||
|  | 			var y = ref.y; | |||
|  | 			var width = ref.width; | |||
|  | 			var height = ref.height; | |||
|  | 			if (done === void 0) done = function() {}; | |||
|  | 
 | |||
|  | 			return convertToImage(canvasId, x, y, width, height, 'bmp', done) | |||
|  | 		} | |||
|  | 	}; | |||
|  | 
 | |||
|  | 	function methods() { | |||
|  | 		var self = this; | |||
|  | 
 | |||
|  | 		var boundWidth = self.width; // 裁剪框默认宽度,即整个画布宽度
 | |||
|  | 		var boundHeight = self.height; // 裁剪框默认高度,即整个画布高度
 | |||
|  | 
 | |||
|  | 		var id = self.id; | |||
|  | 		var targetId = self.targetId; | |||
|  | 		var pixelRatio = self.pixelRatio; | |||
|  | 
 | |||
|  | 		var ref = self.cut; | |||
|  | 		var x = ref.x; | |||
|  | 		if (x === void 0) x = 0; | |||
|  | 		var y = ref.y; | |||
|  | 		if (y === void 0) y = 0; | |||
|  | 		var width = ref.width; | |||
|  | 		if (width === void 0) width = boundWidth; | |||
|  | 		var height = ref.height; | |||
|  | 		if (height === void 0) height = boundHeight; | |||
|  | 
 | |||
|  | 		self.updateCanvas = function(done) { | |||
|  | 			if (self.croperTarget) { | |||
|  | 				//  画布绘制图片
 | |||
|  | 				self.ctx.drawImage( | |||
|  | 					self.croperTarget, | |||
|  | 					self.imgLeft, | |||
|  | 					self.imgTop, | |||
|  | 					self.scaleWidth, | |||
|  | 					self.scaleHeight | |||
|  | 				); | |||
|  | 			} | |||
|  | 			tools_7(self.onBeforeDraw) && self.onBeforeDraw(self.ctx, self); | |||
|  | 
 | |||
|  | 			self.setBoundStyle(self.boundStyle); //	设置边界样式
 | |||
|  | 
 | |||
|  | 			self.ctx.draw(false, done); | |||
|  | 			return self | |||
|  | 		}; | |||
|  | 
 | |||
|  | 		self.pushOrigin = self.pushOrign = function(src) { | |||
|  | 			self.src = src; | |||
|  | 
 | |||
|  | 			tools_7(self.onBeforeImageLoad) && self.onBeforeImageLoad(self.ctx, self); | |||
|  | 
 | |||
|  | 			return getImageInfo({ | |||
|  | 					src: src | |||
|  | 				}) | |||
|  | 				.then(function(res) { | |||
|  | 					var innerAspectRadio = res.width / res.height; | |||
|  | 					var customAspectRadio = width / height; | |||
|  | 
 | |||
|  | 					self.croperTarget = res.path; | |||
|  | 
 | |||
|  | 					if (innerAspectRadio < customAspectRadio) { | |||
|  | 						self.rectX = x; | |||
|  | 						self.baseWidth = width; | |||
|  | 						self.baseHeight = width / innerAspectRadio; | |||
|  | 						self.rectY = y - Math.abs((height - self.baseHeight) / 2); | |||
|  | 					} else { | |||
|  | 						self.rectY = y; | |||
|  | 						self.baseWidth = height * innerAspectRadio; | |||
|  | 						self.baseHeight = height; | |||
|  | 						self.rectX = x - Math.abs((width - self.baseWidth) / 2); | |||
|  | 					} | |||
|  | 
 | |||
|  | 					self.imgLeft = self.rectX; | |||
|  | 					self.imgTop = self.rectY; | |||
|  | 					self.scaleWidth = self.baseWidth; | |||
|  | 					self.scaleHeight = self.baseHeight; | |||
|  | 
 | |||
|  | 					self.update(); | |||
|  | 
 | |||
|  | 					return new Promise(function(resolve) { | |||
|  | 						self.updateCanvas(resolve); | |||
|  | 					}) | |||
|  | 				}) | |||
|  | 				.then(function() { | |||
|  | 					tools_7(self.onImageLoad) && self.onImageLoad(self.ctx, self); | |||
|  | 				}) | |||
|  | 		}; | |||
|  | 
 | |||
|  | 		self.removeImage = function() { | |||
|  | 			self.src = ''; | |||
|  | 			self.croperTarget = ''; | |||
|  | 			return draw(self.ctx) | |||
|  | 		}; | |||
|  | 
 | |||
|  | 		self.getCropperBase64 = function(done) { | |||
|  | 			if (done === void 0) done = function() {}; | |||
|  | 
 | |||
|  | 			CanvasToBase64.convertToBMP({ | |||
|  | 				canvasId: id, | |||
|  | 				x: x, | |||
|  | 				y: y, | |||
|  | 				width: width, | |||
|  | 				height: height | |||
|  | 			}, done); | |||
|  | 		}; | |||
|  | 
 | |||
|  | 		self.getCropperImage = function(opt, fn) { | |||
|  | 			var customOptions = opt; | |||
|  | 
 | |||
|  | 			var canvasOptions = { | |||
|  | 				canvasId: id, | |||
|  | 				x: x, | |||
|  | 				y: y, | |||
|  | 				width: width, | |||
|  | 				height: height | |||
|  | 			}; | |||
|  | 
 | |||
|  | 			var task = function() { | |||
|  | 				return Promise.resolve(); | |||
|  | 			}; | |||
|  | 
 | |||
|  | 			if ( | |||
|  | 				tools_10(customOptions) && | |||
|  | 				customOptions.original | |||
|  | 			) { | |||
|  | 				// original mode
 | |||
|  | 				task = function() { | |||
|  | 					self.targetCtx.drawImage( | |||
|  | 						self.croperTarget, | |||
|  | 						self.imgLeft * pixelRatio, | |||
|  | 						self.imgTop * pixelRatio, | |||
|  | 						self.scaleWidth * pixelRatio, | |||
|  | 						self.scaleHeight * pixelRatio | |||
|  | 					); | |||
|  | 
 | |||
|  | 					canvasOptions = { | |||
|  | 						canvasId: targetId, | |||
|  | 						x: x * pixelRatio, | |||
|  | 						y: y * pixelRatio, | |||
|  | 						width: width * pixelRatio, | |||
|  | 						height: height * pixelRatio | |||
|  | 					}; | |||
|  | 
 | |||
|  | 					return draw(self.targetCtx) | |||
|  | 				}; | |||
|  | 			} | |||
|  | 
 | |||
|  | 			return task() | |||
|  | 				.then(function() { | |||
|  | 					if (tools_10(customOptions)) { | |||
|  | 						canvasOptions = Object.assign({}, canvasOptions, customOptions); | |||
|  | 					} | |||
|  | 
 | |||
|  | 					if (tools_7(customOptions)) { | |||
|  | 						fn = customOptions; | |||
|  | 					} | |||
|  | 
 | |||
|  | 					var arg = canvasOptions.componentContext ? | |||
|  | 						[canvasOptions, canvasOptions.componentContext] : | |||
|  | 						[canvasOptions]; | |||
|  | 
 | |||
|  | 					return canvasToTempFilePath.apply(null, arg) | |||
|  | 				}) | |||
|  | 				.then(function(res) { | |||
|  | 					var tempFilePath = res.tempFilePath; | |||
|  | 
 | |||
|  | 					return tools_7(fn) ? | |||
|  | 						fn.call(self, tempFilePath, null) : | |||
|  | 						tempFilePath | |||
|  | 				}) | |||
|  | 				.catch(function(err) { | |||
|  | 					if (tools_7(fn)) { | |||
|  | 						fn.call(self, null, err); | |||
|  | 					} else { | |||
|  | 						throw err | |||
|  | 					} | |||
|  | 				}) | |||
|  | 		}; | |||
|  | 	} | |||
|  | 
 | |||
|  | 	/** | |||
|  | 	 * 获取最新缩放值 | |||
|  | 	 * @param oldScale 上一次触摸结束后的缩放值 | |||
|  | 	 * @param oldDistance 上一次触摸结束后的双指距离 | |||
|  | 	 * @param zoom 缩放系数 | |||
|  | 	 * @param touch0 第一指touch对象 | |||
|  | 	 * @param touch1 第二指touch对象 | |||
|  | 	 * @returns {*} | |||
|  | 	 */ | |||
|  | 	var getNewScale = function(oldScale, oldDistance, zoom, touch0, touch1) { | |||
|  | 		var xMove, yMove, newDistance; | |||
|  | 		// 计算二指最新距离
 | |||
|  | 		xMove = Math.round(touch1.x - touch0.x); | |||
|  | 		yMove = Math.round(touch1.y - touch0.y); | |||
|  | 		newDistance = Math.round(Math.sqrt(xMove * xMove + yMove * yMove)); | |||
|  | 
 | |||
|  | 		return oldScale + 0.001 * zoom * (newDistance - oldDistance) | |||
|  | 	}; | |||
|  | 
 | |||
|  | 	function update() { | |||
|  | 		var self = this; | |||
|  | 
 | |||
|  | 		if (!self.src) { | |||
|  | 			return | |||
|  | 		} | |||
|  | 
 | |||
|  | 		self.__oneTouchStart = function(touch) { | |||
|  | 			self.touchX0 = Math.round(touch.x); | |||
|  | 			self.touchY0 = Math.round(touch.y); | |||
|  | 		}; | |||
|  | 
 | |||
|  | 		self.__oneTouchMove = function(touch) { | |||
|  | 			var xMove, yMove; | |||
|  | 			// 计算单指移动的距离
 | |||
|  | 			if (self.touchended) { | |||
|  | 				return self.updateCanvas() | |||
|  | 			} | |||
|  | 			xMove = Math.round(touch.x - self.touchX0); | |||
|  | 			yMove = Math.round(touch.y - self.touchY0); | |||
|  | 
 | |||
|  | 			var imgLeft = Math.round(self.rectX + xMove); | |||
|  | 			var imgTop = Math.round(self.rectY + yMove); | |||
|  | 
 | |||
|  | 			self.outsideBound(imgLeft, imgTop); | |||
|  | 
 | |||
|  | 			self.updateCanvas(); | |||
|  | 		}; | |||
|  | 
 | |||
|  | 		self.__twoTouchStart = function(touch0, touch1) { | |||
|  | 			var xMove, yMove, oldDistance; | |||
|  | 
 | |||
|  | 			self.touchX1 = Math.round(self.rectX + self.scaleWidth / 2); | |||
|  | 			self.touchY1 = Math.round(self.rectY + self.scaleHeight / 2); | |||
|  | 
 | |||
|  | 			// 计算两指距离
 | |||
|  | 			xMove = Math.round(touch1.x - touch0.x); | |||
|  | 			yMove = Math.round(touch1.y - touch0.y); | |||
|  | 			oldDistance = Math.round(Math.sqrt(xMove * xMove + yMove * yMove)); | |||
|  | 
 | |||
|  | 			self.oldDistance = oldDistance; | |||
|  | 		}; | |||
|  | 
 | |||
|  | 		self.__twoTouchMove = function(touch0, touch1) { | |||
|  | 			var oldScale = self.oldScale; | |||
|  | 			var oldDistance = self.oldDistance; | |||
|  | 			var scale = self.scale; | |||
|  | 			var zoom = self.zoom; | |||
|  | 
 | |||
|  | 			self.newScale = getNewScale(oldScale, oldDistance, zoom, touch0, touch1); | |||
|  | 
 | |||
|  | 			//  设定缩放范围
 | |||
|  | 			self.newScale <= 1 && (self.newScale = 1); | |||
|  | 			self.newScale >= scale && (self.newScale = scale); | |||
|  | 
 | |||
|  | 			self.scaleWidth = Math.round(self.newScale * self.baseWidth); | |||
|  | 			self.scaleHeight = Math.round(self.newScale * self.baseHeight); | |||
|  | 			var imgLeft = Math.round(self.touchX1 - self.scaleWidth / 2); | |||
|  | 			var imgTop = Math.round(self.touchY1 - self.scaleHeight / 2); | |||
|  | 
 | |||
|  | 			self.outsideBound(imgLeft, imgTop); | |||
|  | 
 | |||
|  | 			self.updateCanvas(); | |||
|  | 		}; | |||
|  | 
 | |||
|  | 		self.__xtouchEnd = function() { | |||
|  | 			self.oldScale = self.newScale; | |||
|  | 			self.rectX = self.imgLeft; | |||
|  | 			self.rectY = self.imgTop; | |||
|  | 		}; | |||
|  | 	} | |||
|  | 
 | |||
|  | 	var handle = { | |||
|  | 		//  图片手势初始监测
 | |||
|  | 		touchStart: function touchStart(e) { | |||
|  | 			var self = this; | |||
|  | 			var ref = e.touches; | |||
|  | 			var touch0 = ref[0]; | |||
|  | 			var touch1 = ref[1]; | |||
|  | 
 | |||
|  | 			if (!self.src) { | |||
|  | 				return | |||
|  | 			} | |||
|  | 
 | |||
|  | 			setTouchState(self, true, null, null); | |||
|  | 
 | |||
|  | 			// 计算第一个触摸点的位置,并参照改点进行缩放
 | |||
|  | 			self.__oneTouchStart(touch0); | |||
|  | 
 | |||
|  | 			// 两指手势触发
 | |||
|  | 			if (e.touches.length >= 2) { | |||
|  | 				self.__twoTouchStart(touch0, touch1); | |||
|  | 			} | |||
|  | 		}, | |||
|  | 
 | |||
|  | 		//  图片手势动态缩放
 | |||
|  | 		touchMove: function touchMove(e) { | |||
|  | 			var self = this; | |||
|  | 			var ref = e.touches; | |||
|  | 			var touch0 = ref[0]; | |||
|  | 			var touch1 = ref[1]; | |||
|  | 
 | |||
|  | 			if (!self.src) { | |||
|  | 				return | |||
|  | 			} | |||
|  | 
 | |||
|  | 			setTouchState(self, null, true); | |||
|  | 
 | |||
|  | 			// 单指手势时触发
 | |||
|  | 			if (e.touches.length === 1) { | |||
|  | 				self.__oneTouchMove(touch0); | |||
|  | 			} | |||
|  | 			// 两指手势触发
 | |||
|  | 			if (e.touches.length >= 2) { | |||
|  | 				self.__twoTouchMove(touch0, touch1); | |||
|  | 			} | |||
|  | 		}, | |||
|  | 
 | |||
|  | 		touchEnd: function touchEnd(e) { | |||
|  | 			var self = this; | |||
|  | 
 | |||
|  | 			if (!self.src) { | |||
|  | 				return | |||
|  | 			} | |||
|  | 
 | |||
|  | 			setTouchState(self, false, false, true); | |||
|  | 			self.__xtouchEnd(); | |||
|  | 		} | |||
|  | 	}; | |||
|  | 
 | |||
|  | 	function cut() { | |||
|  | 		var self = this; | |||
|  | 		var boundWidth = self.width; // 裁剪框默认宽度,即整个画布宽度
 | |||
|  | 		var boundHeight = self.height; | |||
|  | 		// 裁剪框默认高度,即整个画布高度
 | |||
|  | 		var ref = self.cut; | |||
|  | 		var x = ref.x; | |||
|  | 		if (x === void 0) x = 0; | |||
|  | 		var y = ref.y; | |||
|  | 		if (y === void 0) y = 0; | |||
|  | 		var width = ref.width; | |||
|  | 		if (width === void 0) width = boundWidth; | |||
|  | 		var height = ref.height; | |||
|  | 		if (height === void 0) height = boundHeight; | |||
|  | 
 | |||
|  | 		/** | |||
|  | 		 * 设置边界 | |||
|  | 		 * @param imgLeft 图片左上角横坐标值 | |||
|  | 		 * @param imgTop 图片左上角纵坐标值 | |||
|  | 		 */ | |||
|  | 		self.outsideBound = function(imgLeft, imgTop) { | |||
|  | 			self.imgLeft = imgLeft >= x ? | |||
|  | 				x : | |||
|  | 				self.scaleWidth + imgLeft - x <= width ? | |||
|  | 				x + width - self.scaleWidth : | |||
|  | 				imgLeft; | |||
|  | 
 | |||
|  | 			self.imgTop = imgTop >= y ? | |||
|  | 				y : | |||
|  | 				self.scaleHeight + imgTop - y <= height ? | |||
|  | 				y + height - self.scaleHeight : | |||
|  | 				imgTop; | |||
|  | 		}; | |||
|  | 
 | |||
|  | 		/** | |||
|  | 		 * 设置边界样式 | |||
|  | 		 * @param color	边界颜色 | |||
|  | 		 */ | |||
|  | 		self.setBoundStyle = function(ref) { | |||
|  | 			if (ref === void 0) ref = {}; | |||
|  | 			var color = ref.color; | |||
|  | 			if (color === void 0) color = '#04b00f'; | |||
|  | 			var mask = ref.mask; | |||
|  | 			if (mask === void 0) mask = 'rgba(0, 0, 0, 0.3)'; | |||
|  | 			var lineWidth = ref.lineWidth; | |||
|  | 			if (lineWidth === void 0) lineWidth = 1; | |||
|  | 
 | |||
|  | 			var half = lineWidth / 2; | |||
|  | 			var boundOption = [{ | |||
|  | 					start: { | |||
|  | 						x: x - half, | |||
|  | 						y: y + 10 - half | |||
|  | 					}, | |||
|  | 					step1: { | |||
|  | 						x: x - half, | |||
|  | 						y: y - half | |||
|  | 					}, | |||
|  | 					step2: { | |||
|  | 						x: x + 10 - half, | |||
|  | 						y: y - half | |||
|  | 					} | |||
|  | 				}, | |||
|  | 				{ | |||
|  | 					start: { | |||
|  | 						x: x - half, | |||
|  | 						y: y + height - 10 + half | |||
|  | 					}, | |||
|  | 					step1: { | |||
|  | 						x: x - half, | |||
|  | 						y: y + height + half | |||
|  | 					}, | |||
|  | 					step2: { | |||
|  | 						x: x + 10 - half, | |||
|  | 						y: y + height + half | |||
|  | 					} | |||
|  | 				}, | |||
|  | 				{ | |||
|  | 					start: { | |||
|  | 						x: x + width - 10 + half, | |||
|  | 						y: y - half | |||
|  | 					}, | |||
|  | 					step1: { | |||
|  | 						x: x + width + half, | |||
|  | 						y: y - half | |||
|  | 					}, | |||
|  | 					step2: { | |||
|  | 						x: x + width + half, | |||
|  | 						y: y + 10 - half | |||
|  | 					} | |||
|  | 				}, | |||
|  | 				{ | |||
|  | 					start: { | |||
|  | 						x: x + width + half, | |||
|  | 						y: y + height - 10 + half | |||
|  | 					}, | |||
|  | 					step1: { | |||
|  | 						x: x + width + half, | |||
|  | 						y: y + height + half | |||
|  | 					}, | |||
|  | 					step2: { | |||
|  | 						x: x + width - 10 + half, | |||
|  | 						y: y + height + half | |||
|  | 					} | |||
|  | 				} | |||
|  | 			]; | |||
|  | 
 | |||
|  | 			// 绘制半透明层
 | |||
|  | 			self.ctx.beginPath(); | |||
|  | 			self.ctx.setFillStyle(mask); | |||
|  | 			self.ctx.fillRect(0, 0, x, boundHeight); | |||
|  | 			self.ctx.fillRect(x, 0, width, y); | |||
|  | 			self.ctx.fillRect(x, y + height, width, boundHeight - y - height); | |||
|  | 			self.ctx.fillRect(x + width, 0, boundWidth - x - width, boundHeight); | |||
|  | 			self.ctx.fill(); | |||
|  | 
 | |||
|  | 			boundOption.forEach(function(op) { | |||
|  | 				self.ctx.beginPath(); | |||
|  | 				self.ctx.setStrokeStyle(color); | |||
|  | 				self.ctx.setLineWidth(lineWidth); | |||
|  | 				self.ctx.moveTo(op.start.x, op.start.y); | |||
|  | 				self.ctx.lineTo(op.step1.x, op.step1.y); | |||
|  | 				self.ctx.lineTo(op.step2.x, op.step2.y); | |||
|  | 				self.ctx.stroke(); | |||
|  | 			}); | |||
|  | 		}; | |||
|  | 	} | |||
|  | 
 | |||
|  | 	var version = "1.3.9"; | |||
|  | 
 | |||
|  | 	var WeCropper = function WeCropper(params) { | |||
|  | 		var self = this; | |||
|  | 		var _default = {}; | |||
|  | 
 | |||
|  | 		validator(self, DEFAULT); | |||
|  | 
 | |||
|  | 		Object.keys(DEFAULT).forEach(function(key) { | |||
|  | 			_default[key] = DEFAULT[key].default; | |||
|  | 		}); | |||
|  | 		Object.assign(self, _default, params); | |||
|  | 
 | |||
|  | 		self.prepare(); | |||
|  | 		self.attachPage(); | |||
|  | 		self.createCtx(); | |||
|  | 		self.observer(); | |||
|  | 		self.cutt(); | |||
|  | 		self.methods(); | |||
|  | 		self.init(); | |||
|  | 		self.update(); | |||
|  | 
 | |||
|  | 		return self | |||
|  | 	}; | |||
|  | 
 | |||
|  | 	WeCropper.prototype.init = function init() { | |||
|  | 		var self = this; | |||
|  | 		var src = self.src; | |||
|  | 
 | |||
|  | 		self.version = version; | |||
|  | 
 | |||
|  | 		typeof self.onReady === 'function' && self.onReady(self.ctx, self); | |||
|  | 
 | |||
|  | 		if (src) { | |||
|  | 			self.pushOrign(src); | |||
|  | 		} else { | |||
|  | 			self.updateCanvas(); | |||
|  | 		} | |||
|  | 		setTouchState(self, false, false, false); | |||
|  | 
 | |||
|  | 		self.oldScale = 1; | |||
|  | 		self.newScale = 1; | |||
|  | 
 | |||
|  | 		return self | |||
|  | 	}; | |||
|  | 
 | |||
|  | 	Object.assign(WeCropper.prototype, handle); | |||
|  | 
 | |||
|  | 	WeCropper.prototype.prepare = prepare; | |||
|  | 	WeCropper.prototype.observer = observer; | |||
|  | 	WeCropper.prototype.methods = methods; | |||
|  | 	WeCropper.prototype.cutt = cut; | |||
|  | 	WeCropper.prototype.update = update; | |||
|  | 
 | |||
|  | 	return WeCropper; | |||
|  | 
 | |||
|  | }))); |