微信小程序简单的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 浏览器事件介绍
Mar 30 Javascript
密码强度检测效果实现原理与代码
Jan 04 Javascript
浅析Node.js查找字符串功能
Sep 03 Javascript
jquery中radio checked问题
Mar 16 Javascript
深入理解javascript作用域第二篇之词法作用域和动态作用域
Jul 24 Javascript
原生JavaScript实现AJAX、JSONP
Feb 07 Javascript
详解Vue生命周期的示例
Mar 10 Javascript
JS学习笔记之闭包小案例分析
May 29 Javascript
小程序实现搜索框功能
Mar 26 Javascript
vue动态路由:路由参数改变,视图不更新问题的解决
Nov 05 Javascript
原生JS利用transform实现banner的无限滚动示例代码
Jun 15 Javascript
Vue切换div显示隐藏,多选,单选代码解析
Jul 14 Javascript
小程序实现分类页
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
模拟flock实现文件锁定
2007/02/14 PHP
PHP5多态性与动态绑定介绍
2015/04/03 PHP
php实现将wav文件转换成图像文件并在页面中显示的方法
2015/04/21 PHP
讲解WordPress中用于获取评论模板和搜索表单的PHP函数
2015/12/28 PHP
php使用str_shuffle()函数生成随机字符串的方法分析
2017/02/17 PHP
2017年最新PHP经典面试题目汇总(上篇)
2017/03/17 PHP
js 键盘记录实现(兼容FireFox和IE)
2010/02/07 Javascript
JavaScript的各种常见函数定义方法
2014/09/16 Javascript
用jquery模仿的a的title属性的例子
2014/10/22 Javascript
JS实现的另类手风琴效果网页内容切换代码
2015/09/08 Javascript
基于AngularJS+HTML+Groovy实现登录功能
2016/02/17 Javascript
Bootstrap Chart组件使用教程
2016/04/28 Javascript
Javascript动画效果(2)
2016/10/11 Javascript
javascript将url解析为json格式的两种方法
2017/08/18 Javascript
bootstrap table实现双击可编辑、添加、删除行功能
2017/09/27 Javascript
使用Bootrap和Vue实现仿百度搜索功能
2017/10/26 Javascript
vue实现购物车选择功能
2020/01/10 Javascript
python3+PyQt5实现文档打印功能
2018/04/24 Python
pytorch 把MNIST数据集转换成图片和txt的方法
2018/05/20 Python
Python使用wget实现下载网络文件功能示例
2018/05/31 Python
一篇文章弄懂Python中所有数组数据类型
2019/06/23 Python
python实现图片二值化及灰度处理方式
2019/12/07 Python
Python读取表格类型文件代码实例
2020/02/17 Python
Python嵌入C/C++进行开发详解
2020/06/09 Python
Python在后台自动解压各种压缩文件的实现方法
2020/11/10 Python
使用phonegap播放音频的实现方法
2017/03/31 HTML / CSS
加拿大奢华时装品牌:Mackage
2018/01/10 全球购物
ProForm英国站点:健身房和健身器材网上商店
2019/06/05 全球购物
如果NULL定义成#define NULL((char *)0)难道不就可以向函数传入不加转换的NULL了吗
2012/02/15 面试题
童装店创业计划书
2014/01/09 职场文书
遥感技术与仪器求职信
2014/02/22 职场文书
研修心得体会
2014/09/04 职场文书
法人身份证明书
2015/06/18 职场文书
养成教育工作总结
2015/08/13 职场文书
MyBatis-Plus 批量插入数据的操作方法
2021/09/25 Java/Android
PostgreSQL基于pgrouting的路径规划处理方法
2022/04/18 PostgreSQL