微信小程序简单的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 相关文章推荐
IE网页js语法错误2行字符1、FF中正常的解决方法
Sep 09 Javascript
js 3秒后跳转页面的实现代码
Mar 10 Javascript
jquery实现用户打分评分特效
May 28 Javascript
jquery实现页面常用的返回顶部效果
Mar 04 Javascript
JQuery查找子元素find()和遍历集合each的方法总结
Mar 07 Javascript
HTML中使背景图片自适应浏览器大小实例详解
Apr 06 Javascript
微信小程序中使用javascript 回调函数
May 11 Javascript
原生js简单实现放大镜特效
May 16 Javascript
JS实现点击循环切换显示内容的方法
Oct 19 Javascript
vue-router命名视图的使用讲解
Jan 19 Javascript
ES6之Proxy的get方法详解
Oct 11 Javascript
echarts 使用formatter 修改鼠标悬浮事件信息操作
Jul 20 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
数据库相关问题
2006/10/09 PHP
PHP简单系统数据添加以及数据删除模块源文件下载
2008/06/07 PHP
PHP 中常量的知识整理
2017/04/14 PHP
PHP实现打包下载文件的方法示例
2017/10/07 PHP
php封装db类连接sqlite3数据库的方法实例
2017/12/19 PHP
jQuery MD5加密实现代码
2010/03/15 Javascript
jQuery 打造动态渐变按钮 详细图文教程
2010/04/25 Javascript
JavaScript 错误处理与调试经验总结
2010/08/10 Javascript
javascript自执行函数之伪命名空间封装法
2010/12/25 Javascript
javascript框架设计读书笔记之模块加载系统
2014/12/02 Javascript
JavaScript中通过提示框跳转页面的方法
2016/02/14 Javascript
laydate.js日期时间选择插件
2017/01/04 Javascript
BootStrap表单宽度设置方法
2017/03/10 Javascript
详解Vue2 SSR 缓存 Api 数据
2017/11/20 Javascript
Vue头像处理方案小结
2018/07/26 Javascript
axios的拦截请求与响应方法
2018/08/11 Javascript
jQuery实现网页拼图游戏
2020/04/22 jQuery
微信小程序的mpvue框架快速上手指南
2019/05/15 Javascript
javascript实现简易的计算器
2020/01/17 Javascript
Angular之jwt令牌身份验证的实现
2020/02/14 Javascript
[04:45]DOTA2-DPC中国联赛正赛 iG vs LBZS 赛后选手采访
2021/03/11 DOTA
python实现多线程暴力破解登陆路由器功能代码分享
2015/01/04 Python
Python中max函数用法实例分析
2015/07/17 Python
在Linux命令行终端中使用python的简单方法(推荐)
2017/01/23 Python
利用Hyperic调用Python实现进程守护
2018/01/02 Python
浅析python中的迭代与迭代对象
2018/10/08 Python
Python实现的矩阵转置与矩阵相乘运算示例
2019/03/26 Python
python调用自定义函数的实例操作
2019/06/26 Python
JBL澳大利亚官方商店:扬声器、耳机和音响系统
2018/05/24 全球购物
自考自我鉴定范文
2013/10/30 职场文书
小学运动会演讲稿
2014/08/25 职场文书
财政专业大学生职业生涯规划书
2014/09/17 职场文书
行政介绍信范文
2015/05/04 职场文书
cf战队宣传语
2015/07/13 职场文书
幼儿园小班教师随笔
2015/08/14 职场文书
Golang解析JSON对象
2022/04/30 Golang