小程序图片裁剪功能简易版,分享前裁剪

该文件主要执行分享前的裁剪
微信后台的download安全域名别忘记设置,否则上线后不能剪切
小程序内是图片是HTTP的要想办法换成https

一.介绍使用

1.基本使用

以商品详情为例:

<template>
  <view class="container">
    <!-- n个布局 -->
    <view wx:if="{{cutData.imageInfor}}">
      <canvas style="width:{{cutData.imageInfor.width}}px;height:{{cutData.imageInfor.height}}px;display:{{cutData.showCanvas ? 'block':'none'}};" canvas-id="cropper"></canvas>
      <!-- 为了看裁剪效果,实际可以没有此元素 -->
      <!-- <image src="{{cutData.savedFilePath}}"></image> -->
    </view>
  </view>
</template>

<script>
import cut from '../../utils/cut';
export default class ProductDetail extends wepy.page {
  // 分享事件,暂时没有做回调事件
  onShareAppMessage() {
    let info = wx.getStorageSync(USER_INFO);
    return {
      title: this.product.baseInfo.name,
      imageUrl: this.cutData.savedFilePath,
      path: "/pages/mine/white_page?pid=" + this.product.baseInfo.productId + "&source=" + info.userId,
      success: function(res) {
        // 转发成功
        console.log('转发成功');
      },
      fail: function(res) {
        // 转发失败
        console.log('转发失败');
      }
    };
  }

  config = {
    navigationBarTitleText: "商品详情"
  };
  data = {
    product: {},
    cutData:{             // 分享剪切处理
      imageInfor:null,
      savedFilePath:'',
      showCanvas:true,    // 初始显示canvas,若初始不显示canvas会裁剪报错
    }
  };

  methods = {
    // 分享事件,显示分享按钮
    handleShare() {
      console.log(1111);
      wx.showShareMenu({
        withShareTicket: true
      });
    },
  };
  // 页面加载事件
  onLoad(option) {
    // 前面n个操作
    this.getData();
  }

  async getData(pid , shop) {
    // 前面n个操作
    let res = await getProductDetail(params);
    if (res.data.code == 200) {
      this.product = res.data.data;
      this.isError = false;
      // 执行裁剪
      this._myCut();
    } else if(res.data.code == 500) {
      // ...
    } else {
      this.isError = true;
    }
    this.$apply();
  }

  // 参见方法,每次onload都运行
  _myCut() {
    if (!this.product.headPics) {
      return ;
    }
    cut.cut(this.product.headPics[0].imgUrl,'cropper'
      ,imageInfor => {   // 得到待分享图片的信息
        this.cutData.imageInfor = imageInfor;
        this.$apply();
      }
      ,savedFilePath => {    // 获取保存到本地的图片信息
        this.cutData.savedFilePath = savedFilePath;
        // 将canvas隐藏,不影响页面布局
        this.cutData.showCanvas = false;
        this.$apply();
        // 清除本地存储的文件列表,但是不包含本次生成的文件
        cut.clearSavedFileList(this.cutData.savedFilePath);
      }
    );

  };
}
</script>
<style lang="less">
</style>

2.注意

  • 在_myCut函数中,得到本地保存路径后的回调内应将canvas隐藏,防止被用户看到
  • 放canvas的view应该放在页面最底部,防止初始出现的时候被用户看到
  • 在得到本地保存路径后的回调内应将微信内保存的其他savedFileList删除,这里如果自己存放了其他资源,可以选择修改cut.js的clearSavedFileList方法.
  • 之所以不在onShareAppMessage方法内之间裁剪(也就是用户点击了分享或者转发才裁剪),是因为onShareAppMessage方法要求返回一个对象,cut.js采用回调实现,cut中的cut方法中回调的值不能被onShareAppMessage拿到,所以放在了getData方法中

二.介绍实现

1.实现

cut.js

export default {

  // 裁剪方法
  cut(url,canvasId,imageInforCB,savedFilePathCB) {
    let that = this;
    const ctx = wx.createCanvasContext('cropper');
    that._getImageInfor(url,ctx,canvasId,imageInforCB,savedFilePathCB);
  },

  // 删除本地存储数据
  clearSavedFileList(currSavedFilePath) {
    wx.getSavedFileList({
      success: function(res) {
        for (let i=0;i<res.fileList.length;i++) {
          if (currSavedFilePath !== res.fileList[i].filePath) {
            wx.removeSavedFile({
              filePath: res.fileList[i].filePath,
              complete: function(res) {
                console.log('本地图片删除结束',res);
              }
            });
          }
        }
      }
    });
  },

  // 获取图片信息
  _getImageInfor(url,ctx,canvasId,imageInforCB,savedFilePathCB) {
    let that = this;
    wx.getImageInfo({
      src: url,
      success: function (imageInfor) {
        console.log('getImageInfo2',imageInfor);
        imageInforCB(imageInfor);
        // 将图画到canvas上
        that._drawImage(ctx,imageInfor,()=>{
          that._getTempFilePath(canvasId,imageInfor,savedFilePathCB);
        });
      },
      fail: function(res) {
        console.log('getImageInfo fail',res);
      },
      complete:function(res) {
        console.log('getImageInfo complete',res);
      }
    });
  },

  // 在canvas上画图
  _drawImage(ctx,imageInfor,cb) {
    ctx.drawImage(imageInfor.path,0,0,imageInfor.width,imageInfor.height);
    ctx.draw(false,()=>{
      console.log('绘制完成');
      cb();
    });
  },

  // 使用canvas剪裁,后获取临时本地路径,
  _getTempFilePath(canvasId,imageInfor,savedFilePathCB) {
    let that = this;
    let cutData = that._computedCutData(imageInfor);
    console.log('cutData',cutData);
    wx.canvasToTempFilePath({
      x: cutData.x,
      y: cutData.y,
      width: imageInfor.width,
      height: imageInfor.height,
      destWidth: cutData.destWidth,
      destHeight: cutData.destHeight,
      canvasId: canvasId,
      success: function(res) {
        console.log('canvasToTempFilePath res',res);
        that._saveImage(res.tempFilePath,savedFilePathCB);
      },
      fail: function(res) {
        console.log('canvasToTempFilePath fail',res);
      },
      complete:function(res) {
        console.log('canvasToTempFilePath complete',res);
      }
    });
  },

  // 将_getTempFilePath得到的临时路径保存到本地
  _saveImage(tempFilePath,savedFilePathCB) {
    wx.saveFile({
      tempFilePath: tempFilePath,
      success: function (res) {
        let savedFilePath = res.savedFilePath;
        console.log('savedFilePath',res);
        savedFilePathCB(savedFilePath);
      },
      fail:function() {
        console.log('saveFile,fail');
      },
      complete:function() {
        console.log('saveFile,complete');
      }
    });
  },

  // 计算裁剪数据,目前由长宽1:1裁成长宽比5:4的图片,裁剪公式 (h-(w/5*4))/2
  _computedCutData(imageInfor) {
    let cutData = {
      x:0,          // canvas剪切左上角x坐标
      y:0,          // canvas剪切左上角y坐标
      destWidth:0,  // 图片裁剪宽度 
      destHeight:0  // 图片裁剪高度
    };
    let cutY = (imageInfor.height-(imageInfor.width/5*4))/2;
    cutData.y = cutY;
    cutData.x = 0;
    cutData.destWidth = imageInfor.width;
    cutData.destHeight = imageInfor.height - cutY*2;
    return cutData;
  }
}

2.注意

1.剪裁前要讲图片画到canvas上,因为调用了canvas的canvasToTempFilePath方法
2.注意cut.js中clearSavedFileList方法是清除除了本次生成的图片之外的所有微信小程序savedFileList,如不希望,可以修改此方法
3._computedCutData是计算裁剪数据,图片将按照得到的结果裁剪,
4.本cut.js的_computedCutData裁剪尺寸是图片宽度不变,高度上下各裁剪掉宽度的十分之一
5.wx.canvasToTempFilePath方法要在draw的回调函数中运行才会正确得到结果
5.canvas的display:none;会触发wx.canvasToTempFilePath失败,因此应该首先canvas的display:block,当本地保存路径得到后再display:none即可

三.补充(2018/5/25)

上线之后发现图片剪裁出现问题,当图片宽高都超出2000的时候,不知道为何,小程序闪退,所以这里做了修改,添加了如下方法:

此方法在_getImageInfor方法中调用,保证图片在1000以下

// 重新设定图片宽高比例,因为小程序一裁剪宽高2000左右的就闪退,这里限制到1000以下
  _resetImageSize(imageInfor) {
    let result = imageInfor;
    while(result.width > 1000 && result.height > 1000) {
      result.width = result.width / 2;
      result.height = result.height / 2;
    }
    return result;
  }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值