微信小程序简单的canvas裁剪图片功能详解


Posted in Javascript onJuly 12, 2019

小程序miniso的一个发布内容截图功能,话不多,先上代码

wxml文件:

<view class="cut-1-1 t-c {{cutSelect == 1? 'cut-select':''}}" data-cut="1" bindtap="selectCutType">1:1</view>
<view class="cut-3-4 t-c {{cutSelect == 2? 'cut-select':''}}" data-cut="2" bindtap="selectCutType">3:4</view>
<block wx:for="{{imgList}}" wx:key="{{index}}" >
  <swiper-item>
  <scroll-view scroll-top="{{topNum}}" scroll-y class="imgFile {{cutSelect == 1?'view-1-1':'view-3-4'}}" bindscroll="endTou">
   <image src='{{item}}' mode="widthFix"></image>
  </scroll-view >
  </swiper-item>
</block>
<canvas wx:for="{{imgList}}" wx:for-index="i" canvas-id="myCanvas_{{i}}" style="width: {{width[i]?width[i]*2:750}}rpx; height: {{height[i]?height[i]*2:750}}rpx;"></canvas>

这里是对多张图片进行统一处理,用户选了哪种截图比例,所有图片用统一规格裁剪。

因为简单,不提供缩放和左右移动,所以只能裁剪竖长图,不支持横长图裁剪。

topNum用于scroll-view的reset处理

wxss文件

.view-1-1 {
 width: 750rpx;
 height: 750rpx;
 overflow: hidden;
}

.view-3-4 {
 width: 750rpx;
 height: 750rpx;
 padding: 0 94rpx;
 box-sizing: border-box;
 overflow: hidden;
}

canvas {
 position: absolute;
 /* display: none; */
 left: -999rpx;
 z-index: 0;
}

裁剪比例的样式,1:1裁剪使用750rpx,3:4使用padding进行视觉上的拉长
接下来就是重要的代码部分了

js文件

cutPic() {
 const _this = this
 if (this.data.cutting) {
  return
 }
 let promiseList = [], ctx = []
 _this.data.imgList.forEach((v, i) => {
  promiseList.push(_this.draw(ctx, v, i))
 })
 wx.showLoading({
  title: '截取中...',
  icon: 'none'
 })
 this.setData({
  cutting: true
 })
 Promise.all(promiseList).then((arr) => {
  wx.setStorageSync("interimImagesList", _this.data.imgFileList)
  _this.uploadPic()
 }, err => {
 })
 },

使用微信自带api,wx.chooseImage将图片保存在imgList数组里,因为裁剪图片用canvas处理会有一定的延迟,所以使用promise进行异步处理

//获取竖向滑动坐标
 endTou(e) {
 const _this = this
 let y = 'y[' + (_this.data.currentIndex - 1) + '].top'
 _this.setData({
  [y]: e.detail.scrollTop
 })
 },

定义的y数组用于记录每张图片截取的位置。

//绘制
 draw(ctx, v, i) {
 const _this = this
 let width, height
 return new Promise((resolve, reject) => {
  ctx[i] = wx.createCanvasContext(`myCanvas_${i}`)
  wx.getImageInfo({
  src: v,
  success: function (res) {
   width = 'width[' + i + ']'
   height = 'height[' + i + ']'
   var str = res.height / res.width;//图片的宽高比
   _this.setData({
   [width]: 375,
   [height]: 375 * str
   }, () => {
   ctx[i].drawImage(v, 0, 0, _this.data.width[i], _this.data.height[i])
   ctx[i].draw(false, () => {
    setTimeout(() => {
    wx.canvasToTempFilePath({//调用方法,开始截取
     x: 0,
     y: _this.data.y[i] ? _this.data.cutSelect == 1 ? _this.data.y[i].top : _this.data.y[i].top / 0.75 : 0,
     width: 375,
     height: _this.data.cutSelect == 1 ? 375 : 500,
     destWidth: 375,
     destHeight: _this.data.cutSelect == 1 ? 375 : 500,
     canvasId: 'myCanvas_' + i,
     success: function (res) {
     resolve(res.tempFilePath)
     console.info('canvas', res.tempFilePath)
     let img = 'imgFileList[' + i + ']'
     _this.setData({
      [img]: res.tempFilePath
     })
     },
     fail: function (err) {
     reject(err)
     console.info(err)
     }
    })
    }, 1000) // 渲染时间
   })
   })
  }
  })
 })
 },

渲染图片最重要的一步是获得宽高比,所以在canvas绘制之前使用getImageInfo获取到图片信息,var str=res.height/res.width获得高宽比例。

canvas绘制图片是需要时间,所以setTime了个1秒,不然截出来的图是失败的。这里也可以使用递归的方式来绘制

canvas 代码就不给出了,可以自己搜一下。

总结

一个简单的canvas截图就制作完成了。值得注意的是canvas渲染是需要时间的。
这也算是一个简单的练手吧,下次有什么复杂的截图功能再分享出来吧。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js操作Xml(向服务器发送Xml,处理服务器返回的Xml)(IE下有效)
Jan 30 Javascript
JQuery 选择器、过滤器介绍
Feb 14 Javascript
javascript自定义函数参数传递为字符串格式
Jul 29 Javascript
JavaScript 学习笔记之语句
Jan 14 Javascript
js获取数组的最后一个元素
Apr 14 Javascript
bootstrap table配置参数例子
Jan 05 Javascript
Node.js 中exports 和 module.exports 的区别
Mar 14 Javascript
微信小程序调用微信支付接口的实现方法
Apr 29 Javascript
gulp构建小程序的方法步骤
May 31 Javascript
layui监听工具栏的实例(操作列表按钮)
Sep 10 Javascript
jquery中attr、prop、data区别与用法分析
Sep 25 jQuery
vue ref如何获取子组件属性值
Mar 31 Vue.js
小程序实现分类页
Jul 12 #Javascript
jquery实现自定义树形表格的方法【自定义树形结构table】
Jul 12 #jQuery
小程序实现搜索框
Jun 19 #Javascript
ECharts地图绘制和钻取简易接口详解
Jul 12 #Javascript
vue cli安装使用less的教程详解
Jul 12 #Javascript
Js通过AES加密后PHP用Openssl解密的方法
Jul 12 #Javascript
django js 实现表格动态标序号的实例代码
Jul 12 #Javascript
You might like
php数组函数序列之array_key_exists() - 查找数组键名是否存在
2011/10/29 PHP
php实现信用卡校验位算法THE LUHN MOD-10示例
2014/05/07 PHP
php简单分页类实现方法
2015/02/26 PHP
php控制文件下载速度的方法
2015/03/24 PHP
php抓取网站图片并保存的实现方法
2015/10/29 PHP
浅谈laravel aliases别名的原理
2019/10/24 PHP
jquery通过select列表选择框对表格数据进行过滤示例
2014/05/07 Javascript
zepto中使用swipe.js制作轮播图附swipeUp,swipeDown不起效果问题
2015/08/27 Javascript
基于javascript实现彩票随机数生成(简单版)
2020/04/17 Javascript
轻松掌握JavaScript装饰者模式
2016/08/27 Javascript
使用InstantClick.js让页面提前加载200ms
2017/09/12 Javascript
详解如何使用webpack在vue项目中写jsx语法
2017/11/08 Javascript
通过封装scroll.js 获取滚动条的值
2018/07/13 Javascript
React中使用UEditor百度富文本的方法
2018/08/22 Javascript
vue中rem的配置的方法示例
2018/08/30 Javascript
vue将单页面改造成多页面应用的方法
2018/11/25 Javascript
javascript实现鼠标点击生成文字特效
2019/12/24 Javascript
[00:47]TI7不朽珍藏III——沙王不朽展示
2017/07/15 DOTA
[14:50]2018DOTA2亚洲邀请赛开幕式
2018/04/03 DOTA
Python异常学习笔记
2015/02/03 Python
numpy.std() 计算矩阵标准差的方法
2018/07/11 Python
python从zip中删除指定后缀文件(推荐)
2019/12/05 Python
Python PIL库图片灰化处理
2020/04/07 Python
Jupyter Notebook打开任意文件夹操作
2020/04/14 Python
django Layui界面点击弹出对话框并请求逻辑生成分页的动态表格实例
2020/05/12 Python
如何理解Python中包的引入
2020/05/29 Python
Keras构建神经网络踩坑(解决model.predict预测值全为0.0的问题)
2020/07/07 Python
关于老式浏览器兼容HTML5和CSS3的问题
2016/06/01 HTML / CSS
机械专业毕业生推荐信范文
2013/11/25 职场文书
求职自荐书范文
2013/12/04 职场文书
优质服务演讲稿
2014/05/14 职场文书
银行业务授权委托书
2014/10/10 职场文书
村党支部书记个人对照材料汇报
2014/10/26 职场文书
关于军训的感想
2015/08/07 职场文书
2016年主题党日活动总结
2016/04/05 职场文书
日本十大血腥动漫,那些被禁播的动漫盘点
2022/03/21 日漫