<NME> methods.js
<BEF> /**
 * Created by sail on 2017/6/11.
 */
export default function methods() {
	const self = this

} from './utils/promisify'
import CanvasToBase64 from './utils/canvas2base64'

export default function methods () {
  const self = this

  const boundWidth = self.width // 裁剪框默认宽度，即整个画布宽度
			//  画布绘制图片
			self.ctx.drawImage(self.croperTarget, self.imgLeft, self.imgTop, self.scaleWidth, self.scaleHeight)
		}
		typeof self.onBeforeDraw === 'function' && self.onBeforeDraw(self.ctx, self)

		self.setBoundStyle() //	设置边界样式
		self.ctx.draw()

  let {

	self.pushOrign = (src) => {
		self.src = src

		typeof self.onBeforeImageLoad === 'function' && self.onBeforeImageLoad(self.ctx, self)

		wx.getImageInfo({
			src,
      //  画布绘制图片
      self.ctx.drawImage(
        self.croperTarget,
        self.imgLeft,
        self.imgTop,
        self.scaleWidth,
        self.scaleHeight
      )
    }
    isFunc(self.onBeforeDraw) && self.onBeforeDraw(self.ctx, self)

    self.setBoundStyle(self.boundStyle) //	设置边界样式

    if (self.type !== '2d') {
      self.ctx.draw(false, done)
    }

    done && done()
    return self
  }

  self.pushOrigin = self.pushOrign = (src) => {
				self.scaleHeight = self.baseHeight

				self.updateCanvas()

				typeof self.onImageLoad === 'function' && self.onImageLoad(self.ctx, self)
			}
		})

        .then(res => {
          let innerAspectRadio = res.width / res.height
          let customAspectRadio = width / height

	self.getCropperImage = (...args) => {
		const { id } = self
		const ARG_TYPE = toString.call(args[0])

		switch (ARG_TYPE) {
			case '[object Object]':
            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((resolve) => {
					destWidth: width * quality / (deviceRadio * 10),
					destHeight: height * quality / (deviceRadio * 10),
					success (res) {
						typeof args[args.length - 1] === 'function' && args[args.length - 1](res.tempFilePath)
					}
				}); break
			case '[object Function]':
    self.src = ''
    self.croperTarget = ''

    if (self.type === '2d') {
      return self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height)
    } else {
					destWidth: width / deviceRadio,
					destHeight: height / deviceRadio,
					success (res) {
						typeof args[args.length - 1] === 'function' && args[args.length - 1](res.tempFilePath)
					}
				}); break
		}
      height
    }, done)
  }

  self.getCropperImage = (opt, fn) => {
    const customOptions = Object.assign({fileType: 'jpg'}, opt)
    const callback = isFunc(opt) ? opt : isFunc(fn) ? fn : null

    let canvasOptions = {
      canvasId: id,
      x: x,
      y: y,
      width: width,
      height: height
    }

    if (self.type === '2d') {
      canvasOptions.canvas = self.canvas
    }

    let task = () => Promise.resolve()

    if (customOptions.original) {
      // original mode
      task = () => {
        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(() => {
        Object.assign(canvasOptions, customOptions)
        const arg = canvasOptions.componentContext
          ? [canvasOptions, canvasOptions.componentContext]
          : [canvasOptions]

        return canvasToTempFilePath.apply(null, arg)
      })
      .then(res => {
        const tempFilePath = res.tempFilePath
        return callback
          ? callback.call(self, tempFilePath, null)
          : tempFilePath
      })
      .catch((err) => {
        if (callback) {
          callback.call(self, null, err)
        } else {
          throw err
        }
      })
  }
}

<MSG> src: update main/methods/utils

<DFF> @@ -1,6 +1,8 @@
 /**
  * Created by sail on 2017/6/11.
  */
+import { isFunction } from './utils'
+
 export default function methods() {
 	const self = this
 
@@ -14,7 +16,7 @@ export default function methods() {
 			//  画布绘制图片
 			self.ctx.drawImage(self.croperTarget, self.imgLeft, self.imgTop, self.scaleWidth, self.scaleHeight)
 		}
-		typeof self.onBeforeDraw === 'function' && self.onBeforeDraw(self.ctx, self)
+    isFunction(self.onBeforeDraw) && self.onBeforeDraw(self.ctx, self)
 
 		self.setBoundStyle() //	设置边界样式
 		self.ctx.draw()
@@ -23,8 +25,8 @@ export default function methods() {
 
 	self.pushOrign = (src) => {
 		self.src = src
-
-		typeof self.onBeforeImageLoad === 'function' && self.onBeforeImageLoad(self.ctx, self)
+    
+    isFunction(self.onBeforeImageLoad) && self.onBeforeImageLoad(self.ctx, self)
 
 		wx.getImageInfo({
 			src,
@@ -53,8 +55,8 @@ export default function methods() {
 				self.scaleHeight = self.baseHeight
 
 				self.updateCanvas()
-
-				typeof self.onImageLoad === 'function' && self.onImageLoad(self.ctx, self)
+        
+        isFunction(self.onImageLoad) && self.onImageLoad(self.ctx, self)
 			}
 		})
 
@@ -65,6 +67,7 @@ export default function methods() {
 	self.getCropperImage = (...args) => {
 		const { id } = self
 		const ARG_TYPE = toString.call(args[0])
+		const fn = args[args.length - 1]
 
 		switch (ARG_TYPE) {
 			case '[object Object]':
@@ -84,7 +87,10 @@ export default function methods() {
 					destWidth: width * quality / (deviceRadio * 10),
 					destHeight: height * quality / (deviceRadio * 10),
 					success (res) {
-						typeof args[args.length - 1] === 'function' && args[args.length - 1](res.tempFilePath)
+            isFunction(fn) && fn.call(self, res.tempFilePath)
+					},
+					fail (res) {
+            isFunction(fn) && fn.call(self, null)
 					}
 				}); break
 			case '[object Function]':
@@ -97,7 +103,10 @@ export default function methods() {
 					destWidth: width / deviceRadio,
 					destHeight: height / deviceRadio,
 					success (res) {
-						typeof args[args.length - 1] === 'function' && args[args.length - 1](res.tempFilePath)
+            isFunction(fn) && fn.call(self, res.tempFilePath)
+					},
+					fail (res) {
+            isFunction(fn) && fn.call(self, null)
 					}
 				}); break
 		}

src: update main/methods/utils