Skip to content

在mpvue中实现“自定义裁剪组件”

Sail edited this page Apr 17, 2018 · 1 revision

we-cropper可以轻松地应用在mpvue框架中,实现“自定义裁剪组件”

在小程序中,canvas-id通过setData赋值后,会导致其上下文失效,具体原因请戳这里 ,目前可以在mpvue模板中写死canvas-id,we-cropper的功能均能正常使用

安装we-cropper

npm install we-cropper --save

封装组件:components/we-cropper.vue

<template>
  <canvas 
    canvas-id="__we_cropper__"
    @touchstart="touchstart"
    @touchmove="touchmove"
    @touchend="touchend"
    disable-scroll
    :style="{ width: _width + 'px', height: _height + 'px', background: 'rgba(0, 0, 0, .8)' }">
  </canvas>  
</template>

<script>
import WeCropper from 'we-cropper'

const CANVAS_ID = '__we_cropper__'

export default {
  name: 'WeCropper',
  props: {
    option: {
      type: Object
    }
  },
  data () {
    return {
      _we_cropper: null
    }
  },
  computed: {
    _width () {
      return this.option.width
    },
    _height () {
      return this.option.height
    }
  },
  methods: {
    touchstart ($event) {
      this._we_cropper.touchStart($event.mp)
    },
    touchmove ($event) {
      this._we_cropper.touchMove($event.mp)
    },
    touchend ($event) {
      this._we_cropper.touchEnd($event.mp)
    },
    pushOrigin (src) {
      this._we_cropper.pushOrign(src)
    },
    updateCanvas () {
      this._we_cropper.updateCanvas()
    },
    getCropperBase64 () {
      return new Promise((resolve, reject) => {
        this._we_cropper.getCropperImage(src => {
          src ? resolve(src) : reject()
        })
      })
    },
    getCropperImage () {
      return new Promise((resolve, reject) => {
        this._we_cropper.getCropperImage(src => {
          src ? resolve(src) : reject()
        })
      })
    }
  },
  mounted () {
    this._we_cropper = new WeCropper(Object.assign(this.option, {
      id: CANVAS_ID
    }))
    .on('ready', (...args) => {
      this.$emit('ready', ...args)
    })
    .on('beforeImageLoad', (...args) => {
      this.$emit('beforeImageLoad', ...args)
    })
    .on('imageLoad', (...args) => {
      this.$emit('imageLoad', ...args)
    })
    .on('beforeDraw', (...args) => {
      this.$emit('beforeDraw', ...args)
    })
    .updateCanvas()
  }
}
</script>

在Page中使用组件

<template>
  <div>
    <we-cropper 
      :option="cropperOpt"
      @ready="cropperReady"
      @beforeDraw="cropperBeforeDraw"
      @beforeImageLoad="cropperLoad"
      ></we-cropper>
    <div class="cropper-buttons">
      <div
        class="upload"
        @tap="uploadTap">
        上传图片
      </div>
      <div
        class="getCropperImage"
        @tap="getCropperImage">
        生成图片
      </div>
    </div>
  </div>
</template>

<script>
import WeCropper from '@/components/we-cropper'

const device = wx.getSystemInfoSync()
const width = device.windowWidth
const height = device.windowHeight - 50
const getComponentByTag = (parent, tag) => {
  for (let c of parent.$children) {
    if (c.$options._componentTag === tag) {
      return c
    }
  }
}

export default {
  data () {
    return {
      wecropper: null,
      cropperOpt: {
        width,
        height,
        scale: 2.5,
        zoom: 8,
        cut: {
          x: (width - 300) / 2,
          y: (height - 300) / 2,
          width: 300,
          height: 300
        }
      }
    }
  },

  components: {
    WeCropper
  },

  methods: {
    cropperReady (...args) {
      console.log('cropper ready!')
    },
    cropperLoad (...args) {
      console.log('image loaded')
    },
    cropperBeforeDraw (...args) {
      // Todo: 绘制水印等等
    },
    uploadTap () {
      wx.chooseImage({
        count: 1, // 默认9
        sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
        sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
        success: (res) => {
          const src = res.tempFilePaths[0]
          //  获取裁剪图片资源后,给data添加src属性及其值

          this.wecropper.pushOrigin(src)
        }
      })
    },
    getCropperImage () {
      this.wecropper.getCropperImage()
        .then((src) => {
          wx.previewImage({
            current: '', // 当前显示图片的http链接
            urls: [src] // 需要预览的图片http链接列表
          })
        })
        .catch(e => {
          console.error('获取图片失败')
        })
    }
  },

  mounted () {
    this.wecropper = getComponentByTag(this, 'we-cropper')
  }
}
</script>

<style>
.cropper-wrapper{
    position: relative;
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    justify-content: center;
    height: 100%;
    background-color: #e5e5e5;
}

.cropper-buttons{
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    justify-content: center;
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 50px;
    line-height: 50px;
}

.cropper-buttons .upload, .cropper-buttons .getCropperImage{
    width: 50%;
    text-align: center;
}

.cropper{
    position: absolute;
    top: 0;
    left: 0;
}

.cropper-buttons{
    background-color: rgba(0, 0, 0, 0.95);
    color: #04b00f;
}
</style>