微信小程序简单的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 相关文章推荐
对JavaScript的eval()中使用函数的进一步讨论
Jul 26 Javascript
javaScript 删除字符串空格多种方法小结
Oct 24 Javascript
jquery实现加载等待效果示例
Sep 25 Javascript
探讨js中的双感叹号判断
Nov 11 Javascript
jQuery分别获取选中的复选框值的示例
Jun 17 Javascript
js实现可旋转的立方体模型
Oct 16 Javascript
通过修改360抢票的刷新频率和突破8车次限制实现方法
Jan 04 Javascript
Vue.js 2.0中select级联下拉框实例
Mar 06 Javascript
vue实现表格数据的增删改查
Jul 10 Javascript
响应式框架Bootstrap栅格系统的实例
Dec 19 Javascript
解决vue动态为数据添加新属性遇到的问题
Sep 18 Javascript
Vue项目如何引入bootstrap、elementUI、echarts
Nov 26 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写的带缓存数据功能的mysqli类
2012/09/06 PHP
兼容ie6浏览器的php下载文件代码分享
2014/07/14 PHP
删除PHP数组中的重复元素的实现代码
2017/04/10 PHP
PHP-FPM 设置多pool及配置文件重写操作示例
2019/10/02 PHP
js根据给定的日期计算当月有多少天实现思路及代码
2013/02/25 Javascript
使用js实现雪花飘落效果
2013/08/26 Javascript
JavaScript/Js脚本处理html元素的自定义属性解析(亲测兼容Firefox与IE)
2013/11/25 Javascript
深入理解JavaScript系列(40):设计模式之组合模式详解
2015/03/04 Javascript
纯Javascript实现ping功能的方法
2015/03/20 Javascript
jQuery+html5+css3实现圆角无刷新表单带输入验证功能代码
2015/08/21 Javascript
JS实现弹性菜单效果代码
2015/09/07 Javascript
IE6-IE9使用JSON、table.innerHTML所引发的问题
2015/12/22 Javascript
详解支持Angular 2的表格控件
2017/01/19 Javascript
vue动态生成dom并且自动绑定事件
2017/04/19 Javascript
JavaScript实现的可变动态数字键盘控件方式实例代码
2017/07/15 Javascript
微信小程序wx.getImageInfo()如何获取图片信息
2018/01/26 Javascript
vue注册组件的几种方式总结
2018/03/08 Javascript
如何优雅地取消 JavaScript 异步任务
2020/03/22 Javascript
Vue 请求传公共参数的操作
2020/07/31 Javascript
JS实现选项卡插件的两种写法(jQuery和class)
2020/12/30 jQuery
[53:21]2014 DOTA2国际邀请赛中国区预选赛5.21 DT VS LGD-CDEC
2014/05/22 DOTA
Python中input和raw_input的一点区别
2014/10/21 Python
Python模拟三级菜单效果
2017/09/11 Python
Python多线程处理实例详解【单进程/多进程】
2019/01/30 Python
python binascii 进制转换实例
2019/06/12 Python
Django logging配置及使用详解
2019/07/23 Python
分享8点超级有用的Python编程建议(推荐)
2019/10/13 Python
Python如何使用turtle库绘制图形
2020/02/26 Python
Jmeter HTTPS接口测试证书导入过程图解
2020/07/22 Python
新加坡最早生产电动滑板车的制造商之一:FunsToTheFore
2020/09/08 全球购物
初中三年毕业生的自我评价分享
2014/02/14 职场文书
十八届三中全会宣传方案
2014/02/21 职场文书
国贸专业毕业求职信
2014/06/11 职场文书
前台接待岗位职责
2015/02/03 职场文书
董事长助理岗位职责
2015/02/11 职场文书
2015年度班主任自我评价
2015/03/11 职场文书