DESKTOP-MK04A0R\chuck преди 3 години
ревизия
17f501f5ea
променени са 38 файла, в които са добавени 1999 реда и са изтрити 0 реда
  1. 31 0
      .eslintrc.js
  2. 14 0
      .gitignore
  3. 15 0
      doc/README.md
  4. BIN
      doc/example.jpeg
  5. 5 0
      miniprogram/app.js
  6. 12 0
      miniprogram/app.json
  7. 109 0
      miniprogram/pages/camera/camera.js
  8. 3 0
      miniprogram/pages/camera/camera.json
  9. 36 0
      miniprogram/pages/camera/camera.wxml
  10. 84 0
      miniprogram/pages/camera/camera.wxss
  11. 41 0
      miniprogram/pages/index/index.js
  12. 5 0
      miniprogram/pages/index/index.json
  13. 8 0
      miniprogram/pages/index/index.wxml
  14. 12 0
      miniprogram/pages/index/index.wxss
  15. 7 0
      miniprogram/sitemap.json
  16. 20 0
      plugin/components/hello-component.js
  17. 4 0
      plugin/components/hello-component.json
  18. 4 0
      plugin/components/hello-component.wxml
  19. 7 0
      plugin/components/hello-component.wxss
  20. 1117 0
      plugin/components/image-cropper/image-cropper.js
  21. 3 0
      plugin/components/image-cropper/image-cropper.json
  22. 24 0
      plugin/components/image-cropper/image-cropper.wxml
  23. 143 0
      plugin/components/image-cropper/image-cropper.wxss
  24. 21 0
      plugin/index.js
  25. 106 0
      plugin/pages/bank-card/bank-card.js
  26. 3 0
      plugin/pages/bank-card/bank-card.json
  27. 6 0
      plugin/pages/bank-card/bank-card.wxml
  28. 1 0
      plugin/pages/bank-card/bank-card.wxss
  29. 79 0
      plugin/pages/cropper/cropper.js
  30. 3 0
      plugin/pages/cropper/cropper.json
  31. 3 0
      plugin/pages/cropper/cropper.wxml
  32. 1 0
      plugin/pages/cropper/cropper.wxss
  33. 7 0
      plugin/pages/hello-page.js
  34. 1 0
      plugin/pages/hello-page.json
  35. 4 0
      plugin/pages/hello-page.wxml
  36. 1 0
      plugin/pages/hello-page.wxss
  37. 11 0
      plugin/plugin.json
  38. 48 0
      project.config.json

+ 31 - 0
.eslintrc.js

@@ -0,0 +1,31 @@
+/*
+ * Eslint config file
+ * Documentation: https://eslint.org/docs/user-guide/configuring/
+ * Install the Eslint extension before using this feature.
+ */
+module.exports = {
+  env: {
+    es6: true,
+    browser: true,
+    node: true,
+  },
+  ecmaFeatures: {
+    modules: true,
+  },
+  parserOptions: {
+    ecmaVersion: 2018,
+    sourceType: 'module',
+  },
+  globals: {
+    wx: true,
+    App: true,
+    Page: true,
+    getCurrentPages: true,
+    getApp: true,
+    Component: true,
+    requirePlugin: true,
+    requireMiniProgram: true,
+  },
+  // extends: 'eslint:recommended',
+  rules: {},
+}

+ 14 - 0
.gitignore

@@ -0,0 +1,14 @@
+# Windows
+[Dd]esktop.ini
+Thumbs.db
+$RECYCLE.BIN/
+
+# macOS
+.DS_Store
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+
+# Node.js
+node_modules/

+ 15 - 0
doc/README.md

@@ -0,0 +1,15 @@
+# 插件文档标题
+
+## 二级标题
+
+### 三级标题
+
+这个文件用于书写插件文档,引用图片时必须以**相对路径**引用 ***doc*** 目录下的本地图片,不能使用网络图片或非 ***doc*** 目录下的图片。以下是相对路径的引用示例:
+
+![链接](./example.jpeg)
+
+使用编辑器下方的上传按钮可以上传插件文档,上传的内容包括 doc 目录下的 README.md 和图片。
+
+
+
+

BIN
doc/example.jpeg


+ 5 - 0
miniprogram/app.js

@@ -0,0 +1,5 @@
+// app.js
+App({
+  onLaunch() {
+  }
+})

+ 12 - 0
miniprogram/app.json

@@ -0,0 +1,12 @@
+{
+  "pages": [
+    "pages/index/index"
+  ],
+  "plugins": {
+    "hello-plugin": {
+      "version": "dev",
+      "provider": "wxffb7d9420210609d"
+    }
+  },
+  "sitemapLocation": "sitemap.json"
+}

+ 109 - 0
miniprogram/pages/camera/camera.js

@@ -0,0 +1,109 @@
+const app = getApp()
+let ctxWidth = '';
+let ctxHeight = '';
+let ctx = null; //Camera
+let canvaCtx=null;//canvas
+Page({
+  data: {
+ 
+  },
+  changeText() {
+    wx.getSystemInfo({
+      success: res => {
+        let convasX = res.screenWidth / 4; //遮罩层上下的高度(生成canvas的起始横坐标)
+        let convasY = res.screenHeight / 5; //遮罩层左右的宽度(生成canvas的起始纵坐标)
+        let canvasWidth = convasX * 3; //中间裁剪部位的宽度
+        let canvasHeight = convasY * 3; //中间裁剪部位的高度
+        let convasXL = convasX / 2;
+        ctxWidth = canvasWidth; //canvas的宽度
+        ctxHeight = canvasHeight; //canvas的高度
+        this.setData({
+          info: res,
+          canvasWidth,
+          canvasHeight,
+          convasX,
+          convasXL,
+          convasY
+        })
+      }
+    })
+  },
+  onLoad: function () {},
+  onShow() {
+    this.changeText()
+  },
+  takePhoto() {
+    ctx = wx.createCameraContext(); //初始化camera
+    ctx.takePhoto({ //生成图片
+      quality: 'high',
+      success: (res) => { //得到图片
+        this.takeCanvas(res.tempImagePath)
+        this.setData({
+          baseImg: res.tempImagePath,
+          isBaseImg: true,
+          isCanvas:true
+        })
+      }
+    })
+  },
+  takeCanvas(path) { //将拍摄的照片绘制到canvas上
+    wx.getImageInfo({
+      src: path,
+      success: imgInfo => {
+        let {info} = this.data;
+        let convasX = imgInfo.width / 4;
+        let convasY = imgInfo.height / 5;
+        let canvasWidth = convasX * 3;
+        let canvasHeight = convasY * 3;
+        let convasXL = convasX / 2;
+        // 我这里宽度和高度都计算了设备比,其实两个值是一样的 ,计算一个就够了
+        let prxHeight = info.windowHeight / imgInfo.height;//计算设备比
+        let prxWidth = info.windowWidth / imgInfo.width;//计算设备比
+        // ctx = wx.createCanvasContext("myCanvas", this);//自定义组件,需要加this
+        canvaCtx = wx.createCanvasContext("myCanvas");//自定义组件,需要加this
+        canvaCtx.drawImage(path,convasXL,(convasY-40),canvasWidth,canvasHeight,0,0,(parseInt(canvasWidth) * prxWidth),(parseInt(canvasHeight) * prxHeight));//绘制到canvas上的位置,canvas的宽高等
+        canvaCtx.draw(true, () => {
+          wx.canvasToTempFilePath({
+            fileType: "jpg",
+            quality: 0.3,
+            canvasId: "myCanvas",
+            success: canvasToPath => {
+              this.setData({
+                isSuccess:true,
+                isBaseImg: false,
+                isCanvas:false,
+                baseImg: canvasToPath.tempFilePath,
+                srcCanvasPath: canvasToPath.tempFilePath
+              })
+            }
+          })
+          // wx.canvasToTempFilePath({
+          //   fileType: "jpg",
+          //   quality: 0.3,
+          //   canvasId: "myCanvas",
+          //   success: canvasToPath => {
+          //     this.setData({
+          //       isBaseImg: false,
+          //       baseImg: canvasToPath.tempFilePath,
+          //       srcCanvasPath: canvasToPath.tempFilePath
+          //     })
+          //   }
+          // }, this)//自定义组件需要加this
+        })
+      }
+    })
+  },
+  clearPhoto(){
+    canvaCtx.clearRect(0,0,ctxWidth, ctxHeight)
+    canvaCtx.draw()
+    this.setData({
+        srcCanvasPath:"",
+        isCanvas:false,
+        isSuccess:false,
+        isBaseImg:false
+    })
+  },
+  confirmBack(){//确定绘制成功后的操作,根据自己的需求写即可
+ 
+  }
+})

+ 3 - 0
miniprogram/pages/camera/camera.json

@@ -0,0 +1,3 @@
+{
+    "component": true
+}

+ 36 - 0
miniprogram/pages/camera/camera.wxml

@@ -0,0 +1,36 @@
+<cover-view class="lary-top" style="height:{{info.statusBarHeight}}px;"></cover-view>
+<camera class="camera-photo" frame-size="small" device-position="{{devBack}}" flash="off" binderror="error" style="width:{{info.windowWidth}}px;height:{{info.windowHeight}}px;top:{{info.statusBarHeight-200}}px">
+	<cover-view class="page-flex" style="width:{{info.windowWidth}}px; height:{{info.windowHeight}}px;">
+		<cover-view style="height:{{info.windowHeight}}px;" class="page-mask page-mask-lr"></cover-view>
+		<cover-view class="page-content" style="height:{{info.windowHeight}}px;">
+			<cover-view class="page-mask" style="height:{{convasY-40}}px;"></cover-view>
+			<cover-view style="width:{{canvasWidth}}px; height:{{canvasHeight}}px;margin:auto"></cover-view>
+			<cover-view class="page-mask tackPhoto" style="height:{{convasY+40}}px">
+                <cover-view class="confirm-photo" bindtap="takePhoto">确定</cover-view>
+                <cover-view bindtap="cancelPhoto" class="cancel">取消</cover-view>
+            </cover-view>
+		</cover-view>
+		<cover-view style="height:{{info.windowHeight}}px;" class="page-mask page-mask-lr"></cover-view>
+	</cover-view>
+    <cover-view class="id-card">
+        请拍摄身份证
+        <cover-view class="id-card-text">人像面</cover-view>
+    </cover-view>
+</camera>
+<canvas wx:if="{{isCanvas}}" class="canvas-style" canvas-id="myCanvas" style="width:{{canvasWidth}}px; height:{{canvasHeight}}px;"></canvas>
+ 
+<cover-image wx:if="{{isBaseImg}}" class="base-img" mode="aspectFit" style="width:{{info.windowWidth}}px;height:{{info.windowHeight}}px;top:{{info.statusBarHeight}}px" src="{{baseImg}}"></cover-image>
+<cover-view wx:if="{{isSuccess}}" style="width:{{info.windowWidth}}px;height:{{info.windowHeight}}px;top:{{info.statusBarHeight}}px;" class="success-img">
+    <cover-image style="width:{{canvasWidth}}px; height:{{canvasHeight}}px;margin:{{convasY-40}}px auto;" src="{{srcCanvasPath}}"></cover-image>
+    <cover-view class="after-img-tips" style="color:#fff">
+        <!-- 取消绘制,重新绘制 -->
+        <!-- <cover-image class="back" src="../../../assets/back.png" catchtap="clearPhoto"></cover-image> -->
+        <cover-view class="back" catchtap="clearPhoto">重新绘制</cover-view>
+        <!-- 确定绘制,返回到相应的页面,或者隐藏camera组件 -->
+        <!-- <cover-image class="back" src="../../../assets/icon_05-min.png" catchtap="confirmBack"></cover-image> -->
+        <cover-view class="back" catchtap="confirmBack">绘制完成</cover-view>
+    </cover-view>
+</cover-view>
+
+<image-cropper id="image-cropper" limit_move="{{true}}" disable_rotate="{{true}}" width="{{width}}" height="{{height}}" imgSrc="{{src}}" bindload="cropperload" bindimageload="loadimage" bindtapcut="clickcut"></image-cropper>
+

+ 84 - 0
miniprogram/pages/camera/camera.wxss

@@ -0,0 +1,84 @@
+.lary-top{
+    position: fixed;
+    z-index: 101;
+    top: 0;
+    width: 100%;
+    background:#3b8bff
+  }
+  .camera-photo{
+      position: fixed;
+      z-index: 100;
+      overflow: hidden;
+  }
+  .page-flex{
+      display: flex;
+  }
+  .page-mask{
+      background-color: rgba(0,0,0,0.6);
+    }
+    .page-mask-lr{
+      width: 90rpx;
+    }
+    .page-content{
+      flex:1
+    }
+    .tackPhoto{
+      color:#fff;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+    .confirm-photo{
+        width: 130rpx;
+        height: 130rpx;
+        background-color: #3b8bff;
+        border-radius: 50%;
+        text-align: center;
+        line-height: 130rpx;
+    }
+    .cancel{
+      position: absolute;
+      right: 90rpx;
+  }
+  .id-card{
+    position: absolute;
+    font-size: 36rpx;
+    color: #fff;
+    top:53%;
+    right: 40rpx;
+    display: flex;
+    align-items: center;
+    transform-origin: right;
+    transform: rotate(90deg);
+  }
+  .id-card-text{
+      color:#3b8bff
+  }
+  .canvas-style{
+    margin: auto;
+    overflow: hidden;
+  }
+  .base-img{
+    position: fixed;
+    z-index: 101;
+  }
+  .success-img{
+    position: fixed;
+    z-index: 101;
+    background-color: black;
+  }
+  .after-img-tips{
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    width: 100%;
+    position: fixed;
+    bottom: 75rpx;
+    padding-left: 60rpx;
+    padding-right: 60rpx;
+    box-sizing: border-box;
+  }
+  .back{
+    width: 141rpx;
+    height: 141rpx;
+  }

+ 41 - 0
miniprogram/pages/index/index.js

@@ -0,0 +1,41 @@
+const plugin = requirePlugin('hello-plugin')
+
+Page({
+  data: {
+    items: [],
+    currentItem: 0
+  },
+  onLoad() {
+    const world = plugin.answer
+  },
+  onShow() {
+    plugin.getOcrResult({
+      success: (res) => {
+        console.log(res)
+        wx.showLoading({
+          title: '0980890890',
+        })
+      },
+      failed: (error) => {
+        console.log(error)
+      }
+    })
+  },
+  goPluginPage(){
+    wx.navigateTo({
+      url: 'plugin://hello-plugin/bank-card?token=123',
+      events: {
+        someEvent: (data) => {
+          console.log(data)
+        }
+      }
+    })
+  },
+  addItem() {
+    this.data.items.push(this.data.currentItem++)
+    this.setData({
+      items: this.data.items,
+      currentItem: this.data.currentItem
+    })
+  }
+})

+ 5 - 0
miniprogram/pages/index/index.json

@@ -0,0 +1,5 @@
+{
+  "usingComponents": {
+    "hello-list": "plugin://hello-plugin/hello-component"
+  }
+}

+ 8 - 0
miniprogram/pages/index/index.wxml

@@ -0,0 +1,8 @@
+<navigator id="nav" url="plugin://hello-plugin/bank-card?token=123">
+  Go to Plugin page
+</navigator>
+
+<button bindtap="goPluginPage">goPluginPage</button>
+<button id="add" bindtap="addItem">Add item</button>
+
+<hello-list items="{{ items }}" />

+ 12 - 0
miniprogram/pages/index/index.wxss

@@ -0,0 +1,12 @@
+/* pages/index/index.wxss */
+#nav {
+  text-align: center;
+  background: #eeeeee;
+  margin: 1em;
+  padding: 1em;
+  border-radius: 5px;
+}
+
+#add {
+  margin: 1em;
+}

+ 7 - 0
miniprogram/sitemap.json

@@ -0,0 +1,7 @@
+{
+  "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
+  "rules": [{
+  "action": "allow",
+  "page": "*"
+  }]
+}

+ 20 - 0
plugin/components/hello-component.js

@@ -0,0 +1,20 @@
+// plugin/components/hello-component.js
+Component({
+  properties: {
+    items: {
+      type: Array,
+      value: [],
+      observer(newVal, oldVal, changedPath) {
+        this.setData({items: newVal})
+      }
+    }
+  },
+
+  data: {
+    items: []
+  },
+
+  methods: {
+
+  }
+})

+ 4 - 0
plugin/components/hello-component.json

@@ -0,0 +1,4 @@
+{
+  "component": true,
+  "usingComponents": {}
+}

+ 4 - 0
plugin/components/hello-component.wxml

@@ -0,0 +1,4 @@
+<!--plugin/components/hello-component.wxml-->
+<view class="container">
+  <text class="item" wx:key="{{ items }}" wx:for="{{ items }}">{{ item }}</text>
+</view>

+ 7 - 0
plugin/components/hello-component.wxss

@@ -0,0 +1,7 @@
+/* plugin/components/hello-component.wxss */
+.container {
+  margin: 1em;
+}
+.item {
+  display: block;
+}

+ 1117 - 0
plugin/components/image-cropper/image-cropper.js

@@ -0,0 +1,1117 @@
+Component({
+    properties: {
+        /**     
+         * 图片路径
+         */
+        'imgSrc': {
+            type: String
+        },
+        /**
+         * 裁剪框高度
+         */
+        'height': {
+            type: Number,
+            value: 200
+        },
+        /**
+         * 裁剪框宽度
+         */
+        'width': {
+            type: Number,
+            value: 200
+        },
+        /**
+         * 裁剪框最小尺寸
+         */
+        'min_width': {
+            type: Number,
+            value: 100
+        },
+        'min_height': {
+            type: Number,
+            value: 100
+        },
+        /**
+         * 裁剪框最大尺寸
+         */
+        'max_width': {
+            type: Number,
+            value: 300
+        },
+        'max_height': {
+            type: Number,
+            value: 300
+        },
+        /**
+         * 裁剪框禁止拖动
+         */
+        'disable_width': {
+            type: Boolean,
+            value: false
+        },
+        'disable_height': {
+            type: Boolean,
+            value: false
+        },
+        /**
+         * 锁定裁剪框比例
+         */
+        'disable_ratio': {
+            type: Boolean,
+            value: false
+        },
+        /**
+         * 生成的图片尺寸相对剪裁框的比例
+         */
+        'export_scale': {
+            type: Number,
+            value: 3
+        },
+        /**
+         * 生成的图片质量0-1
+         */
+        'quality': {
+            type: Number,
+            value: 1
+        },
+        'cut_top': {
+            type: Number,
+            value: null
+        },
+        'cut_left': {
+            type: Number,
+            value: null
+        },
+        /**
+         * canvas上边距(不设置默认不显示)
+         */
+        'canvas_top': {
+            type: Number,
+            value: null
+        },
+        /**
+         * canvas左边距(不设置默认不显示)
+         */
+        'canvas_left': {
+            type: Number,
+            value: null
+        },
+        /**
+         * 图片宽度
+         */
+        'img_width': {
+            type: null,
+            value: null
+        },
+        /**
+         * 图片高度
+         */
+        'img_height': {
+            type: null,
+            value: null
+        },
+        /**
+         * 图片缩放比
+         */
+        'scale': {
+            type: Number,
+            value: 1
+        },
+        /**
+         * 图片旋转角度
+         */
+        'angle': {
+            type: Number,
+            value: 0
+        },
+        /**
+         * 最小缩放比
+         */
+        'min_scale': {
+            type: Number,
+            value: 0.5
+        },
+        /**
+         * 最大缩放比
+         */
+        'max_scale': {
+            type: Number,
+            value: 2
+        },
+        /**
+         * 是否禁用旋转
+         */
+        'disable_rotate': {
+            type: Boolean,
+            value: false
+        },
+        /**
+         * 是否限制移动范围(剪裁框只能在图片内)
+         */
+        'limit_move': {
+            type: Boolean,
+            value: false
+        }
+    },
+    data: {
+        el: 'image-cropper', //暂时无用
+        info: wx.getSystemInfoSync(),
+        MOVE_THROTTLE: null, //触摸移动节流settimeout
+        MOVE_THROTTLE_FLAG: true, //节流标识
+        INIT_IMGWIDTH: 0, //图片设置尺寸,此值不变(记录最初设定的尺寸)
+        INIT_IMGHEIGHT: 0, //图片设置尺寸,此值不变(记录最初设定的尺寸)
+        TIME_BG: null, //背景变暗延时函数
+        TIME_CUT_CENTER: null,
+        _touch_img_relative: [{
+            x: 0,
+            y: 0
+        }], //鼠标和图片中心的相对位置
+        _flag_cut_touch: false, //是否是拖动裁剪框
+        _hypotenuse_length: 0, //双指触摸时斜边长度
+        _flag_img_endtouch: false, //是否结束触摸
+        _flag_bright: true, //背景是否亮
+        _canvas_overflow: true, //canvas缩略图是否在屏幕外面
+        _canvas_width: 200,
+        _canvas_height: 200,
+        origin_x: 0.5, //图片旋转中心
+        origin_y: 0.5, //图片旋转中心
+        _cut_animation: false, //是否开启图片和裁剪框过渡
+        _img_top: wx.getSystemInfoSync().windowHeight / 2, //图片上边距
+        _img_left: wx.getSystemInfoSync().windowWidth / 2, //图片左边距
+        watch: {
+            //监听截取框宽高变化
+            width(value, that) {
+                    if (value < that.data.min_width) {
+                        that.setData({
+                            width: that.data.min_width
+                        });
+                    }
+                    that._computeCutSize();
+                },
+                height(value, that) {
+                    if (value < that.data.min_height) {
+                        that.setData({
+                            height: that.data.min_height
+                        });
+                    }
+                    that._computeCutSize();
+                },
+                angle(value, that) {
+                    //停止居中裁剪框,继续修改图片位置
+                    that._moveStop();
+                    if (that.data.limit_move) {
+                        if (that.data.angle % 90) {
+                            that.setData({
+                                angle: Math.round(that.data.angle / 90) * 90
+                            });
+                            return;
+                        }
+                    }
+                },
+                _cut_animation(value, that) {
+                    //开启过渡300毫秒之后自动关闭
+                    clearTimeout(that.data._cut_animation_time);
+                    if (value) {
+                        that.data._cut_animation_time = setTimeout(() => {
+                            that.setData({
+                                _cut_animation: false
+                            });
+                        }, 300)
+                    }
+                },
+                limit_move(value, that) {
+                    if (value) {
+                        if (that.data.angle % 90) {
+                            that.setData({
+                                angle: Math.round(that.data.angle / 90) * 90
+                            });
+                        }
+                        that._imgMarginDetectionScale();
+                        !that.data._canvas_overflow && that._draw();
+                    }
+                },
+                canvas_top(value, that) {
+                    that._canvasDetectionPosition();
+                },
+                canvas_left(value, that) {
+                    that._canvasDetectionPosition();
+                },
+                imgSrc(value, that) {
+                    that.pushImg();
+                },
+                cut_top(value, that) {
+                    that._cutDetectionPosition();
+                    if (that.data.limit_move) {
+                        !that.data._canvas_overflow && that._draw();
+                    }
+                },
+                cut_left(value, that) {
+                    that._cutDetectionPosition();
+                    if (that.data.limit_move) {
+                        !that.data._canvas_overflow && that._draw();
+                    }
+                }
+        }
+    },
+    attached() {
+        this.data.info = wx.getSystemInfoSync();
+        //启用数据监听
+        this._watcher();
+        this.data.INIT_IMGWIDTH = this.data.img_width;
+        this.data.INIT_IMGHEIGHT = this.data.img_height;
+        this.setData({
+            _canvas_height: this.data.height,
+            _canvas_width: this.data.width,
+        });
+        this._initCanvas();
+        this.data.imgSrc && (this.data.imgSrc = this.data.imgSrc);
+        //根据开发者设置的图片目标尺寸计算实际尺寸
+        this._initImageSize();
+        //设置裁剪框大小>设置图片尺寸>绘制canvas
+        this._computeCutSize();
+        //检查裁剪框是否在范围内
+        this._cutDetectionPosition();
+        //检查canvas是否在范围内
+        this._canvasDetectionPosition();
+        //初始化完成
+        this.triggerEvent('load', {
+            cropper: this
+        });
+    },
+    methods: {
+        /**
+         * 上传图片
+         */
+        upload() {
+                let that = this;
+                wx.chooseImage({
+                    count: 1,
+                    sizeType: ['original', 'compressed'],
+                    sourceType: ['album', 'camera'],
+                    success(res) {
+                        const tempFilePaths = res.tempFilePaths[0];
+                        that.pushImg(tempFilePaths);
+                        wx.showLoading({
+                            title: '加载中...'
+                        })
+                    }
+                })
+            },
+            /**
+             * 返回图片信息
+             */
+            getImg(getCallback) {
+                this._draw(() => {
+                    wx.canvasToTempFilePath({
+                        width: this.data.width * this.data.export_scale,
+                        height: Math.round(this.data.height * this.data.export_scale),
+                        destWidth: this.data.width * this.data.export_scale,
+                        destHeight: Math.round(this.data.height) * this.data.export_scale,
+                        fileType: 'png',
+                        quality: this.data.quality,
+                        canvasId: this.data.el,
+                        success: (res) => {
+                            getCallback({
+                                url: res.tempFilePath,
+                                width: this.data.width * this.data.export_scale,
+                                height: this.data.height * this.data.export_scale
+                            });
+                        }
+                    }, this)
+                });
+            },
+            /**
+             * 设置图片动画
+             * {
+             *    x:10,//图片在原有基础上向下移动10px
+             *    y:10,//图片在原有基础上向右移动10px
+             *    angle:10,//图片在原有基础上旋转10deg
+             *    scale:0.5,//图片在原有基础上增加0.5倍
+             * }
+             */
+            setTransform(transform) {
+                if (!transform) return;
+                if (!this.data.disable_rotate) {
+                    this.setData({
+                        angle: transform.angle ? this.data.angle + transform.angle : this.data.angle
+                    });
+                }
+                var scale = this.data.scale;
+                if (transform.scale) {
+                    scale = this.data.scale + transform.scale;
+                    scale = scale <= this.data.min_scale ? this.data.min_scale : scale;
+                    scale = scale >= this.data.max_scale ? this.data.max_scale : scale;
+                }
+                this.data.scale = scale;
+                let cutX = this.data.cut_left;
+                let cutY = this.data.cut_top;
+                if (transform.cutX) {
+                    this.setData({
+                        cut_left: cutX + transform.cutX
+                    });
+                    this.data.watch.cut_left(null, this);
+                }
+                if (transform.cutY) {
+                    this.setData({
+                        cut_top: cutY + transform.cutY
+                    });
+                    this.data.watch.cut_top(null, this);
+                }
+                this.data._img_top = transform.y ? this.data._img_top + transform.y : this.data._img_top;
+                this.data._img_left = transform.x ? this.data._img_left + transform.x : this.data._img_left;
+                //图像边缘检测,防止截取到空白
+                this._imgMarginDetectionScale();
+                //停止居中裁剪框,继续修改图片位置
+                this._moveDuring();
+                this.setData({
+                    scale: this.data.scale,
+                    _img_top: this.data._img_top,
+                    _img_left: this.data._img_left
+                });
+                !this.data._canvas_overflow && this._draw();
+                //可以居中裁剪框了
+                this._moveStop(); //结束操作
+            },
+            /**
+             * 设置剪裁框位置
+             */
+            setCutXY(x, y) {
+                this.setData({
+                    cut_top: y,
+                    cut_left: x
+                });
+            },
+            /**
+             * 设置剪裁框尺寸
+             */
+            setCutSize(w, h) {
+                this.setData({
+                    width: w,
+                    height: h
+                });
+                this._computeCutSize();
+            },
+            /**
+             * 设置剪裁框和图片居中
+             */
+            setCutCenter() {
+                let cut_top = (this.data.info.windowHeight - this.data.height) * 0.5;
+                let cut_left = (this.data.info.windowWidth - this.data.width) * 0.5;
+                //顺序不能变
+                this.setData({
+                    _img_top: this.data._img_top - this.data.cut_top + cut_top,
+                    cut_top: cut_top, //截取的框上边距
+                    _img_left: this.data._img_left - this.data.cut_left + cut_left,
+                    cut_left: cut_left, //截取的框左边距
+                });
+            },
+            _setCutCenter() {
+                let cut_top = (this.data.info.windowHeight - this.data.height) * 0.5;
+                let cut_left = (this.data.info.windowWidth - this.data.width) * 0.5;
+                this.setData({
+                    cut_top: cut_top, //截取的框上边距
+                    cut_left: cut_left, //截取的框左边距
+                });
+            },
+            /**
+             * 设置剪裁框宽度-即将废弃
+             */
+            setWidth(width) {
+                this.setData({
+                    width: width
+                });
+                this._computeCutSize();
+            },
+            /**
+             * 设置剪裁框高度-即将废弃
+             */
+            setHeight(height) {
+                this.setData({
+                    height: height
+                });
+                this._computeCutSize();
+            },
+            /**
+             * 是否锁定旋转
+             */
+            setDisableRotate(value) {
+                this.data.disable_rotate = value;
+            },
+            /**
+             * 是否限制移动
+             */
+            setLimitMove(value) {
+                this.setData({
+                    _cut_animation: true,
+                    limit_move: !!value
+                });
+            },
+            /**
+             * 初始化图片,包括位置、大小、旋转角度
+             */
+            imgReset() {
+                this.setData({
+                    scale: 1,
+                    angle: 0,
+                    _img_top: wx.getSystemInfoSync().windowHeight / 2,
+                    _img_left: wx.getSystemInfoSync().windowWidth / 2,
+                })
+            },
+            /**
+             * 加载(更换)图片
+             */
+            pushImg(src) {
+                if (src) {
+                    this.setData({
+                        imgSrc: src
+                    });
+                    //发现是手动赋值直接返回,交给watch处理
+                    return;
+                }
+
+                // getImageInfo接口传入 src: '' 会导致内存泄漏
+
+                if (!this.data.imgSrc) return;
+                wx.getImageInfo({
+                    src: this.data.imgSrc,
+                    success: (res) => {
+                            this.data.imageObject = res;
+                            //图片非本地路径需要换成本地路径
+                            if (this.data.imgSrc.search(/tmp/) == -1) {
+                                this.setData({
+                                    imgSrc: res.path
+                                });
+                            }
+                            //计算最后图片尺寸
+                            this._imgComputeSize();
+                            if (this.data.limit_move) {
+                                //限制移动,不留空白处理
+                                this._imgMarginDetectionScale();
+                            }
+                            this._draw();
+                        },
+                        fail: (err) => {
+                            this.setData({
+                                imgSrc: ''
+                            });
+                        }
+                });
+            },
+            imageLoad(e) {
+                setTimeout(() => {
+                    this.triggerEvent('imageload', this.data.imageObject);
+
+                })
+            },
+            /**
+             * 设置图片放大缩小
+             */
+            setScale(scale) {
+                if (!scale) return;
+                this.setData({
+                    scale: scale
+                });
+                !this.data._canvas_overflow && this._draw();
+            },
+            /**
+             * 设置图片旋转角度
+             */
+            setAngle(angle) {
+                if (!angle) return;
+                this.setData({
+                    _cut_animation: true,
+                    angle: angle
+                });
+                this._imgMarginDetectionScale();
+                !this.data._canvas_overflow && this._draw();
+            },
+            _initCanvas() {
+                //初始化canvas
+                if (!this.data.ctx) {
+                    this.data.ctx = wx.createCanvasContext("image-cropper", this);
+                }
+            },
+            /**
+             * 根据开发者设置的图片目标尺寸计算实际尺寸
+             */
+            _initImageSize() {
+                //处理宽高特殊单位 %>px
+                if (this.data.INIT_IMGWIDTH && typeof this.data.INIT_IMGWIDTH == "string" && this.data.INIT_IMGWIDTH.indexOf("%") != -1) {
+                    let width = this.data.INIT_IMGWIDTH.replace("%", "");
+                    this.data.INIT_IMGWIDTH = this.data.img_width = this.data.info.windowWidth / 100 * width;
+                }
+                if (this.data.INIT_IMGHEIGHT && typeof this.data.INIT_IMGHEIGHT == "string" && this.data.INIT_IMGHEIGHT.indexOf("%") != -1) {
+                    let height = this.data.img_height.replace("%", "");
+                    this.data.INIT_IMGHEIGHT = this.data.img_height = this.data.info.windowHeight / 100 * height;
+                }
+            },
+            /**
+             * 检测剪裁框位置是否在允许的范围内(屏幕内)
+             */
+            _cutDetectionPosition() {
+                let _cutDetectionPositionTop = () => {
+                        //检测上边距是否在范围内
+                        if (this.data.cut_top < 0) {
+                            this.setData({
+                                cut_top: 0
+                            });
+                        }
+                        if (this.data.cut_top > this.data.info.windowHeight - this.data.height) {
+                            this.setData({
+                                cut_top: this.data.info.windowHeight - this.data.height
+                            });
+                        }
+                    },
+                    _cutDetectionPositionLeft = () => {
+                        //检测左边距是否在范围内
+                        if (this.data.cut_left < 0) {
+                            this.setData({
+                                cut_left: 0
+                            });
+                        }
+                        if (this.data.cut_left > this.data.info.windowWidth - this.data.width) {
+                            this.setData({
+                                cut_left: this.data.info.windowWidth - this.data.width
+                            });
+                        }
+                    };
+                //裁剪框坐标处理(如果只写一个参数则另一个默认为0,都不写默认居中)
+                if (this.data.cut_top == null && this.data.cut_left == null) {
+                    this._setCutCenter();
+                } else if (this.data.cut_top != null && this.data.cut_left != null) {
+                    _cutDetectionPositionTop();
+                    _cutDetectionPositionLeft();
+                } else if (this.data.cut_top != null && this.data.cut_left == null) {
+                    _cutDetectionPositionTop();
+                    this.setData({
+                        cut_left: (this.data.info.windowWidth - this.data.width) / 2
+                    });
+                } else if (this.data.cut_top == null && this.data.cut_left != null) {
+                    _cutDetectionPositionLeft();
+                    this.setData({
+                        cut_top: (this.data.info.windowHeight - this.data.height) / 2
+                    });
+                }
+            },
+            /**
+             * 检测canvas位置是否在允许的范围内(屏幕内)如果在屏幕外则不开启实时渲染
+             * 如果只写一个参数则另一个默认为0,都不写默认超出屏幕外
+             */
+            _canvasDetectionPosition() {
+                if (this.data.canvas_top == null && this.data.canvas_left == null) {
+                    this.data._canvas_overflow = false;
+                    this.setData({
+                        canvas_top: -5000,
+                        canvas_left: -5000
+                    });
+                } else if (this.data.canvas_top != null && this.data.canvas_left != null) {
+                    if (this.data.canvas_top < -this.data.height || this.data.canvas_top > this.data.info.windowHeight) {
+                        this.data._canvas_overflow = true;
+                    } else {
+                        this.data._canvas_overflow = false;
+                    }
+                } else if (this.data.canvas_top != null && this.data.canvas_left == null) {
+                    this.setData({
+                        canvas_left: 0
+                    });
+                } else if (this.data.canvas_top == null && this.data.canvas_left != null) {
+                    this.setData({
+                        canvas_top: 0
+                    });
+                    if (this.data.canvas_left < -this.data.width || this.data.canvas_left > this.data.info.windowWidth) {
+                        this.data._canvas_overflow = true;
+                    } else {
+                        this.data._canvas_overflow = false;
+                    }
+                }
+            },
+            /**
+             * 图片边缘检测-位置
+             */
+            _imgMarginDetectionPosition(scale) {
+                if (!this.data.limit_move) return;
+                let left = this.data._img_left;
+                let top = this.data._img_top;
+                var scale = scale || this.data.scale;
+                let img_width = this.data.img_width;
+                let img_height = this.data.img_height;
+                if (this.data.angle / 90 % 2) {
+                    img_width = this.data.img_height;
+                    img_height = this.data.img_width;
+                }
+                left = this.data.cut_left + img_width * scale / 2 >= left ? left : this.data.cut_left + img_width * scale / 2;
+                left = this.data.cut_left + this.data.width - img_width * scale / 2 <= left ? left : this.data.cut_left + this.data.width - img_width * scale / 2;
+                top = this.data.cut_top + img_height * scale / 2 >= top ? top : this.data.cut_top + img_height * scale / 2;
+                top = this.data.cut_top + this.data.height - img_height * scale / 2 <= top ? top : this.data.cut_top + this.data.height - img_height * scale / 2;
+                this.setData({
+                    _img_left: left,
+                    _img_top: top,
+                    scale: scale
+                })
+            },
+            /**
+             * 图片边缘检测-缩放
+             */
+            _imgMarginDetectionScale() {
+                if (!this.data.limit_move) return;
+                let scale = this.data.scale;
+                let img_width = this.data.img_width;
+                let img_height = this.data.img_height;
+                if (this.data.angle / 90 % 2) {
+                    img_width = this.data.img_height;
+                    img_height = this.data.img_width;
+                }
+                if (img_width * scale < this.data.width) {
+                    scale = this.data.width / img_width;
+                }
+                if (img_height * scale < this.data.height) {
+                    scale = Math.max(scale, this.data.height / img_height);
+                }
+                this._imgMarginDetectionPosition(scale);
+            },
+            _setData(obj) {
+                let data = {};
+                for (var key in obj) {
+                    if (this.data[key] != obj[key]) {
+                        data[key] = obj[key];
+                    }
+                }
+                this.setData(data);
+                return data;
+            },
+            /**
+             * 计算图片尺寸
+             */
+            _imgComputeSize() {
+                let img_width = this.data.img_width,
+                    img_height = this.data.img_height;
+                if (!this.data.INIT_IMGHEIGHT && !this.data.INIT_IMGWIDTH) {
+                    //默认按图片最小边 = 对应裁剪框尺寸
+                    img_width = this.data.imageObject.width;
+                    img_height = this.data.imageObject.height;
+                    if (img_width / img_height > this.data.width / this.data.height) {
+                        img_height = this.data.height;
+                        img_width = this.data.imageObject.width / this.data.imageObject.height * img_height;
+                    } else {
+                        img_width = this.data.width;
+                        img_height = this.data.imageObject.height / this.data.imageObject.width * img_width;
+                    }
+                } else if (this.data.INIT_IMGHEIGHT && !this.data.INIT_IMGWIDTH) {
+                    img_width = this.data.imageObject.width / this.data.imageObject.height * this.data.INIT_IMGHEIGHT;
+                } else if (!this.data.INIT_IMGHEIGHT && this.data.INIT_IMGWIDTH) {
+                    img_height = this.data.imageObject.height / this.data.imageObject.width * this.data.INIT_IMGWIDTH;
+                }
+                this.setData({
+                    img_width: img_width,
+                    img_height: img_height
+                });
+            },
+            //改变截取框大小
+            _computeCutSize() {
+                if (this.data.width > this.data.info.windowWidth) {
+                    this.setData({
+                        width: this.data.info.windowWidth,
+                    });
+                } else if (this.data.width + this.data.cut_left > this.data.info.windowWidth) {
+                    this.setData({
+                        cut_left: this.data.info.windowWidth - this.data.cut_left,
+                    });
+                };
+                if (this.data.height > this.data.info.windowHeight) {
+                    this.setData({
+                        height: this.data.info.windowHeight,
+                    });
+                } else if (this.data.height + this.data.cut_top > this.data.info.windowHeight) {
+                    this.setData({
+                        cut_top: this.data.info.windowHeight - this.data.cut_top,
+                    });
+                }!this.data._canvas_overflow && this._draw();
+            },
+            //开始触摸
+            _start(event) {
+                this.data._flag_img_endtouch = false;
+                if (event.touches.length == 1) {
+                    //单指拖动
+                    this.data._touch_img_relative[0] = {
+                        x: (event.touches[0].clientX - this.data._img_left),
+                        y: (event.touches[0].clientY - this.data._img_top)
+                    }
+                } else {
+                    //双指放大
+                    let width = Math.abs(event.touches[0].clientX - event.touches[1].clientX);
+                    let height = Math.abs(event.touches[0].clientY - event.touches[1].clientY);
+                    this.data._touch_img_relative = [{
+                        x: (event.touches[0].clientX - this.data._img_left),
+                        y: (event.touches[0].clientY - this.data._img_top)
+                    }, {
+                        x: (event.touches[1].clientX - this.data._img_left),
+                        y: (event.touches[1].clientY - this.data._img_top)
+                    }];
+                    this.data._hypotenuse_length = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
+                }!this.data._canvas_overflow && this._draw();
+            },
+            _move_throttle() {
+                //安卓需要节流
+                if (this.data.info.platform == 'android') {
+                    clearTimeout(this.data.MOVE_THROTTLE);
+                    this.data.MOVE_THROTTLE = setTimeout(() => {
+                        this.data.MOVE_THROTTLE_FLAG = true;
+                    }, 1000 / 40)
+                    return this.data.MOVE_THROTTLE_FLAG;
+                } else {
+                    this.data.MOVE_THROTTLE_FLAG = true;
+                }
+            },
+            _move(event) {
+                if (this.data._flag_img_endtouch || !this.data.MOVE_THROTTLE_FLAG) return;
+                this.data.MOVE_THROTTLE_FLAG = false;
+                this._move_throttle();
+                this._moveDuring();
+                if (event.touches.length == 1) {
+                    //单指拖动
+                    let left = (event.touches[0].clientX - this.data._touch_img_relative[0].x),
+                        top = (event.touches[0].clientY - this.data._touch_img_relative[0].y);
+                    //图像边缘检测,防止截取到空白
+                    this.data._img_left = left;
+                    this.data._img_top = top;
+                    this._imgMarginDetectionPosition();
+                    this.setData({
+                        _img_left: this.data._img_left,
+                        _img_top: this.data._img_top
+                    });
+                } else {
+                    //双指放大
+                    let width = (Math.abs(event.touches[0].clientX - event.touches[1].clientX)),
+                        height = (Math.abs(event.touches[0].clientY - event.touches[1].clientY)),
+                        hypotenuse = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)),
+                        scale = this.data.scale * (hypotenuse / this.data._hypotenuse_length),
+                        current_deg = 0;
+                    scale = scale <= this.data.min_scale ? this.data.min_scale : scale;
+                    scale = scale >= this.data.max_scale ? this.data.max_scale : scale;
+                    //图像边缘检测,防止截取到空白
+                    this.data.scale = scale;
+                    this._imgMarginDetectionScale();
+                    //双指旋转(如果没禁用旋转)
+                    let _touch_img_relative = [{
+                        x: (event.touches[0].clientX - this.data._img_left),
+                        y: (event.touches[0].clientY - this.data._img_top)
+                    }, {
+                        x: (event.touches[1].clientX - this.data._img_left),
+                        y: (event.touches[1].clientY - this.data._img_top)
+                    }];
+                    if (!this.data.disable_rotate) {
+                        let first_atan = 180 / Math.PI * Math.atan2(_touch_img_relative[0].y, _touch_img_relative[0].x);
+                        let first_atan_old = 180 / Math.PI * Math.atan2(this.data._touch_img_relative[0].y, this.data._touch_img_relative[0].x);
+                        let second_atan = 180 / Math.PI * Math.atan2(_touch_img_relative[1].y, _touch_img_relative[1].x);
+                        let second_atan_old = 180 / Math.PI * Math.atan2(this.data._touch_img_relative[1].y, this.data._touch_img_relative[1].x);
+                        //当前旋转的角度
+                        let first_deg = first_atan - first_atan_old,
+                            second_deg = second_atan - second_atan_old;
+                        if (first_deg != 0) {
+                            current_deg = first_deg;
+                        } else if (second_deg != 0) {
+                            current_deg = second_deg;
+                        }
+                    }
+                    this.data._touch_img_relative = _touch_img_relative;
+                    this.data._hypotenuse_length = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
+                    //更新视图
+                    this.setData({
+                        angle: this.data.angle + current_deg,
+                        scale: this.data.scale
+                    });
+                }!this.data._canvas_overflow && this._draw();
+            },
+            //结束操作
+            _end(event) {
+                this.data._flag_img_endtouch = true;
+                this._moveStop();
+            },
+            //点击中间剪裁框处理
+            _click(event) {
+                if (!this.data.imgSrc) {
+                    //调起上传
+                    this.upload();
+                    return;
+                }
+                this._draw(() => {
+                    let x = event.detail ? event.detail.x : event.touches[0].clientX;
+                    let y = event.detail ? event.detail.y : event.touches[0].clientY;
+                    if ((x >= this.data.cut_left && x <= (this.data.cut_left + this.data.width)) && (y >= this.data.cut_top && y <= (this.data.cut_top + this.data.height))) {
+                        //生成图片并回调
+                        wx.canvasToTempFilePath({
+                            width: this.data.width * this.data.export_scale,
+                            height: Math.round(this.data.height * this.data.export_scale),
+                            destWidth: this.data.width * this.data.export_scale,
+                            destHeight: Math.round(this.data.height) * this.data.export_scale,
+                            fileType: 'png',
+                            quality: this.data.quality,
+                            canvasId: this.data.el,
+                            success: (res) => {
+                                this.triggerEvent('tapcut', {
+                                    url: res.tempFilePath,
+                                    width: this.data.width * this.data.export_scale,
+                                    height: this.data.height * this.data.export_scale
+                                });
+                            }
+                        }, this)
+                    }
+                });
+            },
+            //渲染
+            _draw(callback) {
+                if (!this.data.imgSrc) return;
+                let draw = () => {
+                    //图片实际大小
+                    let img_width = this.data.img_width * this.data.scale * this.data.export_scale;
+                    let img_height = this.data.img_height * this.data.scale * this.data.export_scale;
+                    //canvas和图片的相对距离
+                    var xpos = this.data._img_left - this.data.cut_left;
+                    var ypos = this.data._img_top - this.data.cut_top;
+                    //旋转画布
+                    this.data.ctx.translate(xpos * this.data.export_scale, ypos * this.data.export_scale);
+                    this.data.ctx.rotate(this.data.angle * Math.PI / 180);
+                    this.data.ctx.drawImage(this.data.imgSrc, -img_width / 2, -img_height / 2, img_width, img_height);
+                    this.data.ctx.draw(false, () => {
+                        callback && callback();
+                    });
+                }
+                if (this.data.ctx.width != this.data.width || this.data.ctx.height != this.data.height) {
+                    //优化拖动裁剪框,所以必须把宽高设置放在离用户触发渲染最近的地方
+                    this.setData({
+                        _canvas_height: this.data.height,
+                        _canvas_width: this.data.width,
+                    }, () => {
+                        //延迟40毫秒防止点击过快出现拉伸或裁剪过多
+                        setTimeout(() => {
+                            draw();
+                        }, 40);
+                    });
+                } else {
+                    draw();
+                }
+            },
+            //裁剪框处理
+            _cutTouchMove(e) {
+                if (this.data._flag_cut_touch && this.data.MOVE_THROTTLE_FLAG) {
+                    if (this.data.disable_ratio && (this.data.disable_width || this.data.disable_height)) return;
+                    //节流
+                    this.data.MOVE_THROTTLE_FLAG = false;
+                    this._move_throttle();
+                    let width = this.data.width,
+                        height = this.data.height,
+                        cut_top = this.data.cut_top,
+                        cut_left = this.data.cut_left,
+                        size_correct = () => {
+                            width = width <= this.data.max_width ? width >= this.data.min_width ? width : this.data.min_width : this.data.max_width;
+                            height = height <= this.data.max_height ? height >= this.data.min_height ? height : this.data.min_height : this.data.max_height;
+                        },
+                        size_inspect = () => {
+                            if ((width > this.data.max_width || width < this.data.min_width || height > this.data.max_height || height < this.data.min_height) && this.data.disable_ratio) {
+                                size_correct();
+                                return false;
+                            } else {
+                                size_correct();
+                                return true;
+                            }
+                        };
+                    height = this.data.CUT_START.height + ((this.data.CUT_START.corner > 1 && this.data.CUT_START.corner < 4 ? 1 : -1) * (this.data.CUT_START.y - e.touches[0].clientY));
+                    switch (this.data.CUT_START.corner) {
+                    case 1:
+                        width = this.data.CUT_START.width + this.data.CUT_START.x - e.touches[0].clientX;
+                        if (this.data.disable_ratio) {
+                            height = width / (this.data.width / this.data.height)
+                        }
+                        if (!size_inspect()) return;
+                        cut_left = this.data.CUT_START.cut_left - (width - this.data.CUT_START.width);
+                        break
+                    case 2:
+                        width = this.data.CUT_START.width + this.data.CUT_START.x - e.touches[0].clientX;
+                        if (this.data.disable_ratio) {
+                            height = width / (this.data.width / this.data.height)
+                        }
+                        if (!size_inspect()) return;
+                        cut_top = this.data.CUT_START.cut_top - (height - this.data.CUT_START.height)
+                        cut_left = this.data.CUT_START.cut_left - (width - this.data.CUT_START.width)
+                        break
+                    case 3:
+                        width = this.data.CUT_START.width - this.data.CUT_START.x + e.touches[0].clientX;
+                        if (this.data.disable_ratio) {
+                            height = width / (this.data.width / this.data.height)
+                        }
+                        if (!size_inspect()) return;
+                        cut_top = this.data.CUT_START.cut_top - (height - this.data.CUT_START.height);
+                        break
+                    case 4:
+                        width = this.data.CUT_START.width - this.data.CUT_START.x + e.touches[0].clientX;
+                        if (this.data.disable_ratio) {
+                            height = width / (this.data.width / this.data.height)
+                        }
+                        if (!size_inspect()) return;
+                        break
+                    }
+                    if (!this.data.disable_width && !this.data.disable_height) {
+                        this.setData({
+                            width: width,
+                            cut_left: cut_left,
+                            height: height,
+                            cut_top: cut_top,
+                        })
+                    } else if (!this.data.disable_width) {
+                        this.setData({
+                            width: width,
+                            cut_left: cut_left
+                        })
+                    } else if (!this.data.disable_height) {
+                        this.setData({
+                            height: height,
+                            cut_top: cut_top
+                        })
+                    }
+                    this._imgMarginDetectionScale();
+                }
+            },
+            _cutTouchStart(e) {
+                let currentX = e.touches[0].clientX;
+                let currentY = e.touches[0].clientY;
+                let cutbox_top4 = this.data.cut_top + this.data.height - 30;
+                let cutbox_bottom4 = this.data.cut_top + this.data.height + 20;
+                let cutbox_left4 = this.data.cut_left + this.data.width - 30;
+                let cutbox_right4 = this.data.cut_left + this.data.width + 30;
+
+                let cutbox_top3 = this.data.cut_top - 30;
+                let cutbox_bottom3 = this.data.cut_top + 30;
+                let cutbox_left3 = this.data.cut_left + this.data.width - 30;
+                let cutbox_right3 = this.data.cut_left + this.data.width + 30;
+
+                let cutbox_top2 = this.data.cut_top - 30;
+                let cutbox_bottom2 = this.data.cut_top + 30;
+                let cutbox_left2 = this.data.cut_left - 30;
+                let cutbox_right2 = this.data.cut_left + 30;
+
+                let cutbox_top1 = this.data.cut_top + this.data.height - 30;
+                let cutbox_bottom1 = this.data.cut_top + this.data.height + 30;
+                let cutbox_left1 = this.data.cut_left - 30;
+                let cutbox_right1 = this.data.cut_left + 30;
+                if (currentX > cutbox_left4 && currentX < cutbox_right4 && currentY > cutbox_top4 && currentY < cutbox_bottom4) {
+                    this._moveDuring();
+                    this.data._flag_cut_touch = true;
+                    this.data._flag_img_endtouch = true;
+                    this.data.CUT_START = {
+                        width: this.data.width,
+                        height: this.data.height,
+                        x: currentX,
+                        y: currentY,
+                        corner: 4
+                    }
+                } else if (currentX > cutbox_left3 && currentX < cutbox_right3 && currentY > cutbox_top3 && currentY < cutbox_bottom3) {
+                    this._moveDuring();
+                    this.data._flag_cut_touch = true;
+                    this.data._flag_img_endtouch = true;
+                    this.data.CUT_START = {
+                        width: this.data.width,
+                        height: this.data.height,
+                        x: currentX,
+                        y: currentY,
+                        cut_top: this.data.cut_top,
+                        cut_left: this.data.cut_left,
+                        corner: 3
+                    }
+                } else if (currentX > cutbox_left2 && currentX < cutbox_right2 && currentY > cutbox_top2 && currentY < cutbox_bottom2) {
+                    this._moveDuring();
+                    this.data._flag_cut_touch = true;
+                    this.data._flag_img_endtouch = true;
+                    this.data.CUT_START = {
+                        width: this.data.width,
+                        height: this.data.height,
+                        cut_top: this.data.cut_top,
+                        cut_left: this.data.cut_left,
+                        x: currentX,
+                        y: currentY,
+                        corner: 2
+                    }
+                } else if (currentX > cutbox_left1 && currentX < cutbox_right1 && currentY > cutbox_top1 && currentY < cutbox_bottom1) {
+                    this._moveDuring();
+                    this.data._flag_cut_touch = true;
+                    this.data._flag_img_endtouch = true;
+                    this.data.CUT_START = {
+                        width: this.data.width,
+                        height: this.data.height,
+                        cut_top: this.data.cut_top,
+                        cut_left: this.data.cut_left,
+                        x: currentX,
+                        y: currentY,
+                        corner: 1
+                    }
+                }
+            },
+            _cutTouchEnd(e) {
+                this._moveStop();
+                this.data._flag_cut_touch = false;
+            },
+            //停止移动时需要做的操作
+            _moveStop() {
+                //清空之前的自动居中延迟函数并添加最新的
+                clearTimeout(this.data.TIME_CUT_CENTER);
+                this.data.TIME_CUT_CENTER = setTimeout(() => {
+                        //动画启动
+                        if (!this.data._cut_animation) {
+                            this.setData({
+                                _cut_animation: true
+                            });
+                        }
+                        this.setCutCenter();
+                    }, 1000)
+                    //清空之前的背景变化延迟函数并添加最新的
+                clearTimeout(this.data.TIME_BG);
+                this.data.TIME_BG = setTimeout(() => {
+                    if (this.data._flag_bright) {
+                        this.setData({
+                            _flag_bright: false
+                        });
+                    }
+                }, 2000)
+            },
+            //移动中
+            _moveDuring() {
+                //清空之前的自动居中延迟函数
+                clearTimeout(this.data.TIME_CUT_CENTER);
+                //清空之前的背景变化延迟函数
+                clearTimeout(this.data.TIME_BG);
+                //高亮背景
+                if (!this.data._flag_bright) {
+                    this.setData({
+                        _flag_bright: true
+                    });
+                }
+            },
+            //监听器
+            _watcher() {
+                Object.keys(this.data).forEach(v => {
+                    this._observe(this.data, v, this.data.watch[v]);
+                })
+            },
+            _observe(obj, key, watchFun) {
+                var val = obj[key];
+                Object.defineProperty(obj, key, {
+                    configurable: true,
+                    enumerable: true,
+                    set: (value) => {
+                            val = value;
+                            watchFun && watchFun(val, this);
+                        },
+                        get() {
+                            if (val && '_img_top|img_left||width|height|min_width|max_width|min_height|max_height|export_scale|cut_top|cut_left|canvas_top|canvas_left|img_width|img_height|scale|angle|min_scale|max_scale'.indexOf(key) != -1) {
+                                let ret = parseFloat(parseFloat(val).toFixed(3));
+                                if (typeof val == "string" && val.indexOf("%") != -1) {
+                                    ret += '%';
+                                }
+                                return ret;
+                            }
+                            return val;
+                        }
+                })
+            },
+            _preventTouchMove() {}
+    }
+})

+ 3 - 0
plugin/components/image-cropper/image-cropper.json

@@ -0,0 +1,3 @@
+{
+	"component": true
+}

+ 24 - 0
plugin/components/image-cropper/image-cropper.wxml

@@ -0,0 +1,24 @@
+<view class='image-cropper' catchtouchmove='_preventTouchMove'>
+    <view class='main' bindtouchend="_cutTouchEnd" bindtouchstart="_cutTouchStart" bindtouchmove="_cutTouchMove" bindtap="_click">
+        <view class='content'>
+            <view class='content_top bg_gray {{_flag_bright?"":"bg_black"}}' style="height:{{cut_top}}px;transition-property:{{_cut_animation?'':'background'}}"></view>
+            <view class='content_middle' style="height:{{height}}px;">
+                <view class='content_middle_left bg_gray {{_flag_bright?"":"bg_black"}}' style="width:{{cut_left}}px;transition-property:{{_cut_animation?'':'background'}}"></view>
+                <view class='content_middle_middle' style="width:{{width}}px;height:{{height}}px;transition-duration: .3s;transition-property:{{_cut_animation?'':'background'}};">
+                    <view class="border border-top-left"></view>
+                    <view class="border border-top-right"></view>
+                    <view class="border border-right-top"></view>
+                    <view class="border border-right-bottom"></view>
+                    <view class="border border-bottom-right"></view>
+                    <view class="border border-bottom-left"></view>
+                    <view class="border border-left-bottom"></view>
+                    <view class="border border-left-top"></view>
+                </view>
+                <view class='content_middle_right bg_gray {{_flag_bright?"":"bg_black"}}' style="transition-property:{{_cut_animation?'':'background'}}"></view>
+            </view>
+            <view class='content_bottom bg_gray {{_flag_bright?"":"bg_black"}}' style="transition-property:{{_cut_animation?'':'background'}}"></view>
+        </view>
+        <image bindload="imageLoad" bindtouchstart="_start" bindtouchmove="_move" bindtouchend="_end" style="width:{{img_width ? img_width + 'px' : 'auto'}};height:{{img_height ? img_height + 'px' : 'auto'}};transform:translate3d({{_img_left-img_width/2}}px,{{_img_top-img_height/2}}px,0) scale({{scale}}) rotate({{angle}}deg);transition-duration:{{_cut_animation?.4:0}}s;" class='img' src='{{imgSrc}}'></image>
+    </view>
+    <canvas canvas-id='image-cropper' disable-scroll="true" style="width:{{_canvas_width * export_scale}}px;height:{{_canvas_height * export_scale}}px;left:{{canvas_left}}px;top:{{canvas_top}}px" class='image-cropper-canvas'></canvas>
+</view>

+ 143 - 0
plugin/components/image-cropper/image-cropper.wxss

@@ -0,0 +1,143 @@
+.image-cropper {
+    background: rgba(14, 13, 13, .8);
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100vw;
+    height: 100vh;
+    z-index: 1;
+}
+
+.image-cropper .main {
+    position: absolute;
+    width: 100vw;
+    height: 100vh;
+    overflow: hidden;
+}
+
+.image-cropper .content {
+    z-index: 9;
+    position: absolute;
+    width: 100vw;
+    height: 100vh;
+    display: flex;
+    flex-direction: column;
+    pointer-events: none;
+}
+
+.image-cropper .bg_black {
+    background: rgba(0, 0, 0, 0.8) !important;
+}
+
+.image-cropper .bg_gray {
+    background: rgba(0, 0, 0, 0.45);
+    transition-duration: .35s;
+}
+
+.image-cropper .content>.content_top {
+    pointer-events: none;
+}
+
+.image-cropper .content>.content_middle {
+    display: flex;
+    height: 200px;
+    width: 100%;
+}
+
+.image-cropper .content_middle_middle {
+    width: 200px;
+    box-sizing: border-box;
+    position: relative;
+    transition-duration: .3s;
+}
+
+.image-cropper .content_middle_right {
+    flex: auto;
+}
+
+.image-cropper .content>.content_bottom {
+    flex: auto;
+}
+
+.image-cropper .img {
+    z-index: 2;
+    top: 0;
+    left: 0;
+    position: absolute;
+    border: none;
+    width: 100%;
+    backface-visibility: hidden;
+    transform-origin: center;
+}
+
+.image-cropper .image-cropper-canvas {
+    position: fixed;
+    background: white;
+    width: 150px;
+    height: 150px;
+    z-index: 10;
+    top: -200%;
+    pointer-events: none;
+}
+
+.image-cropper .border {
+    background: white;
+    pointer-events: auto;
+    position: absolute;
+}
+
+.image-cropper .border-top-left {
+    left: -2.5px;
+    top: -2.5px;
+    height: 2.5px;
+    width: 33rpx;
+}
+
+.image-cropper .border-top-right {
+    right: -2.5px;
+    top: -2.5px;
+    height: 2.5px;
+    width: 33rpx;
+}
+
+.image-cropper .border-right-top {
+    top: -1px;
+    width: 2.5px;
+    height: 30rpx;
+    right: -2.5px;
+}
+
+.image-cropper .border-right-bottom {
+    width: 2.5px;
+    height: 30rpx;
+    right: -2.5px;
+    bottom: -1px;
+}
+
+.image-cropper .border-bottom-left {
+    height: 2.5px;
+    width: 33rpx;
+    bottom: -2.5px;
+    left: -2.5px;
+}
+
+.image-cropper .border-bottom-right {
+    height: 2.5px;
+    width: 33rpx;
+    bottom: -2.5px;
+    right: -2.5px;
+}
+
+.image-cropper .border-left-top {
+    top: -1px;
+    width: 2.5px;
+    height: 30rpx;
+    left: -2.5px;
+}
+
+.image-cropper .border-left-bottom {
+    width: 2.5px;
+    height: 30rpx;
+    left: -2.5px;
+    bottom: -1px;
+}

+ 21 - 0
plugin/index.js

@@ -0,0 +1,21 @@
+module.exports = {
+  getOcrResult({success, failed}) {
+    let key = 'key2222'
+    wx.getStorage({
+      key,
+      encrypt: true, // 若开启加密存储,setStorage 和 getStorage 需要同时声明 encrypt 的值为 true
+      success(res) {
+        wx.removeStorageSync(key)
+        if (res && res.data) {
+          return success(res.data)
+        } else {
+          return fail('未能识别结果')
+        }
+      },
+      fail: (err) =>{
+        wx.removeStorageSync(key)
+        return failed(err)
+      }
+    })
+  }
+}

+ 106 - 0
plugin/pages/bank-card/bank-card.js

@@ -0,0 +1,106 @@
+// plugin/pages/bank-card/bank-card.js
+Page({
+
+    /**
+     * 页面的初始数据
+     */
+    data: {
+
+    },
+
+    /**
+     * 生命周期函数--监听页面加载
+     */
+    onLoad: function (options) {
+        console.log(options)
+    },
+    goCropper: function(){
+        console.log('tiao')
+        wx.navigateTo({
+            url: '../cropper/cropper?id=1',
+            events: {
+              // 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
+              acceptDataFromOpenedPage: function(data) {
+                console.log(data)
+              },
+              someEvent: function(data) {
+                console.log(data)
+              }
+            },
+            success: function(res) {
+              // 通过eventChannel向被打开页面传送数据
+              res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'test' })
+            },
+            fail:(res)=>{
+                console.log(res)
+            }
+        })
+    },
+
+    /**
+     * 生命周期函数--监听页面初次渲染完成
+     */
+    onReady: function () {
+
+    },
+
+    /**
+     * 生命周期函数--监听页面显示
+     */
+    onShow: function () {
+        if(this.data.message){
+            let pages = getCurrentPages();
+            console.log(pages)
+            let prevPage = pages[pages.length - 2];
+            console.log(prevPage)
+            // prevPage.setData({
+            //     ocrResult: 'canshuusushsuu',
+            // })
+            wx.navigateBack({
+                delta: 1,
+            })
+        }
+    },
+    goBackOut: function() {
+        const eventChannel = this.getOpenerEventChannel()
+        eventChannel.emit('someEvent', {data: 'tes2t'})
+        wx.navigateBack({
+            delta: 1,
+        })
+    },
+
+    /**
+     * 生命周期函数--监听页面隐藏
+     */
+    onHide: function () {
+
+    },
+
+    /**
+     * 生命周期函数--监听页面卸载
+     */
+    onUnload: function () {
+
+    },
+
+    /**
+     * 页面相关事件处理函数--监听用户下拉动作
+     */
+    onPullDownRefresh: function () {
+
+    },
+
+    /**
+     * 页面上拉触底事件的处理函数
+     */
+    onReachBottom: function () {
+
+    },
+
+    /**
+     * 用户点击右上角分享
+     */
+    onShareAppMessage: function () {
+
+    }
+})

+ 3 - 0
plugin/pages/bank-card/bank-card.json

@@ -0,0 +1,3 @@
+{
+  "usingComponents": {}
+}

+ 6 - 0
plugin/pages/bank-card/bank-card.wxml

@@ -0,0 +1,6 @@
+<!--plugin/pages/bank-card/bank-card.wxml-->
+<text>plugin/pages/bank-card/bank-card.wxml</text>
+
+<button bindtap="goCropper">goCropper</button>
+
+<button bindtap="goBackOut">返回</button>

+ 1 - 0
plugin/pages/bank-card/bank-card.wxss

@@ -0,0 +1 @@
+/* plugin/pages/bank-card/bank-card.wxss */

+ 79 - 0
plugin/pages/cropper/cropper.js

@@ -0,0 +1,79 @@
+// plugin/pages/cropper/cropper.js
+Page({
+
+    /**
+     * 页面的初始数据
+     */
+    data: {
+
+    },
+
+    /**
+     * 生命周期函数--监听页面加载
+     */
+    onLoad: function (options) {
+        console.log(options)
+    },
+    goBack: function(){
+        // 开启加密存储
+        wx.setStorage({
+            key: "key2222",
+            data: "value",
+            encrypt: true, // 若开启加密存储,setStorage 和 getStorage 需要同时声明 encrypt 的值为 true
+            success() {
+                wx.navigateBack({
+                    delta: 2,
+                })
+            }
+        })
+        
+    },
+    /**
+     * 生命周期函数--监听页面初次渲染完成
+     */
+    onReady: function () {
+
+    },
+
+    /**
+     * 生命周期函数--监听页面显示
+     */
+    onShow: function () {
+
+    },
+
+    /**
+     * 生命周期函数--监听页面隐藏
+     */
+    onHide: function () {
+
+    },
+
+    /**
+     * 生命周期函数--监听页面卸载
+     */
+    onUnload: function () {
+
+    },
+
+    /**
+     * 页面相关事件处理函数--监听用户下拉动作
+     */
+    onPullDownRefresh: function () {
+
+    },
+
+    /**
+     * 页面上拉触底事件的处理函数
+     */
+    onReachBottom: function () {
+
+    },
+
+    /**
+     * 用户点击右上角分享
+     */
+    onShareAppMessage: function () {
+
+    }
+})

+ 3 - 0
plugin/pages/cropper/cropper.json

@@ -0,0 +1,3 @@
+{
+  "usingComponents": {}
+}

+ 3 - 0
plugin/pages/cropper/cropper.wxml

@@ -0,0 +1,3 @@
+<!--plugin/pages/cropper/cropper.wxml-->
+<text>plugin/pages/cropper/cropper.wxml</text>
+<button bindtap="goBack">识别结果后返回</button>

+ 1 - 0
plugin/pages/cropper/cropper.wxss

@@ -0,0 +1 @@
+/* plugin/pages/cropper/cropper.wxss */

+ 7 - 0
plugin/pages/hello-page.js

@@ -0,0 +1,7 @@
+// plugin/pages/hello-page.js
+Page({
+  data: {},
+  onLoad() {
+    console.log('This is a plugin page!')
+  }
+})

+ 1 - 0
plugin/pages/hello-page.json

@@ -0,0 +1 @@
+{}

+ 4 - 0
plugin/pages/hello-page.wxml

@@ -0,0 +1,4 @@
+<!--plugin/pages/hello-page.wxml-->
+<text>
+  This is a plugin page!
+</text>

+ 1 - 0
plugin/pages/hello-page.wxss

@@ -0,0 +1 @@
+/* plugin/pages/hello-page.wxss */

+ 11 - 0
plugin/plugin.json

@@ -0,0 +1,11 @@
+{
+    "publicComponents": {
+        "hello-component": "components/hello-component"
+    },
+    "pages": {
+        "hello-page": "pages/hello-page",
+        "cropper": "pages/cropper/cropper",
+        "bank-card": "pages/bank-card/bank-card"
+    },
+    "main": "index.js"
+}

+ 48 - 0
project.config.json

@@ -0,0 +1,48 @@
+{
+    "miniprogramRoot": "miniprogram/",
+    "pluginRoot": "plugin/",
+    "compileType": "plugin",
+    "setting": {
+        "urlCheck": true,
+        "es6": true,
+        "enhance": true,
+        "postcss": true,
+        "preloadBackgroundData": false,
+        "minified": true,
+        "newFeature": false,
+        "coverView": true,
+        "nodeModules": false,
+        "autoAudits": false,
+        "showShadowRootInWxmlPanel": true,
+        "scopeDataCheck": false,
+        "uglifyFileName": false,
+        "checkInvalidKey": true,
+        "checkSiteMap": true,
+        "uploadWithSourceMap": true,
+        "compileHotReLoad": false,
+        "lazyloadPlaceholderEnable": false,
+        "useMultiFrameRuntime": true,
+        "useApiHook": true,
+        "useApiHostProcess": true,
+        "babelSetting": {
+            "ignore": [],
+            "disablePlugins": [],
+            "outputPath": ""
+        },
+        "useIsolateContext": false,
+        "userConfirmedBundleSwitch": false,
+        "packNpmManually": false,
+        "packNpmRelationList": [],
+        "minifyWXSS": true,
+        "disableUseStrict": false,
+        "minifyWXML": true,
+        "showES6CompileOption": false,
+        "useCompilerPlugins": false,
+        "ignoreUploadUnusedFiles": true
+    },
+    "appid": "wxffb7d9420210609d",
+    "projectname": "mini-ocr-test",
+    "pluginAppid": "wxffb7d9420210609d",
+    "libVersion": "2.21.4",
+    "condition": {}
+}