微信小程序简单的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鼠标悬停特效具体方法
Jun 17 Javascript
一个js控制的导航菜单实例代码
Dec 03 Javascript
javascript动态生成树形菜单的方法
Nov 14 Javascript
谈谈jQuery Ajax用法详解
Nov 27 Javascript
jQuery.form插件的使用及跨域异步上传文件
Apr 27 Javascript
如何使用jquery修改css中带有!important的样式属性
Apr 28 Javascript
jquery select2的使用心得(推荐)
Dec 04 Javascript
Node.js实现文件上传的示例
Jun 28 Javascript
在Vue中使用highCharts绘制3d饼图的方法
Feb 08 Javascript
vue-cli监听组件加载完成的方法
Sep 07 Javascript
微信小程序间使用navigator跳转传值问题实例分析
Mar 27 Javascript
让JavaScript代码更加精简的方法技巧
Jun 01 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
十天学会php(2)
2006/10/09 PHP
php 动态多文件上传
2009/01/18 PHP
PHP中获取文件扩展名的N种方法小结
2012/02/27 PHP
PHP error_log()将错误信息写入一个文件(定义和用法)
2013/10/25 PHP
支持中文和其他编码的php截取字符串函数分享(截取中文字符串)
2014/03/13 PHP
ThinkPHP验证码和分页实例教程
2014/08/22 PHP
thinkPHP5框架自定义验证器实现方法分析
2018/06/11 PHP
用javascript实现分割提取页面所需内容
2007/05/09 Javascript
IE下window.onresize 多次调用与死循环bug处理方法介绍
2013/11/12 Javascript
alert和confirm功能介绍
2014/05/21 Javascript
引用其它js时如何同时处理多个window.onload事件
2014/09/02 Javascript
JavaScript中的变量作用域介绍
2014/12/31 Javascript
zepto.js中tap事件阻止冒泡的实现方法
2015/02/12 Javascript
js实现当前输入框高亮显示的方法
2015/08/19 Javascript
jQuery Easyui使用(一)之可折叠面板的布局手风琴菜单
2016/08/17 Javascript
Vue SSR 组件加载问题
2018/05/02 Javascript
基于vue.js组件实现分页效果
2018/12/29 Javascript
[03:22]DSPL第一期精彩集锦:酷炫到底!
2014/11/07 DOTA
手把手教你用python抢票回家过年(代码简单)
2018/01/21 Python
python3连接MySQL数据库实例详解
2018/05/24 Python
Python使用folium excel绘制point
2019/01/03 Python
python使用paramiko模块通过ssh2协议对交换机进行配置的方法
2019/07/25 Python
FFT快速傅里叶变换的python实现过程解析
2019/10/21 Python
python3+opencv生成不规则黑白mask实例
2020/02/19 Python
Python tkinter之Bind(绑定事件)的使用示例
2021/02/05 Python
详解CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
2016/12/20 HTML / CSS
html5如何在Canvas中实现自定义路径动画示例
2017/09/18 HTML / CSS
毕业实习评语
2014/02/10 职场文书
小学数学课后反思
2014/04/23 职场文书
大三学习计划书范文
2014/05/02 职场文书
社区平安建设方案
2014/05/25 职场文书
企业员工爱岗敬业演讲稿
2014/08/26 职场文书
2014年关工委工作总结
2014/11/17 职场文书
2014年班主任德育工作总结
2014/12/05 职场文书
求职自荐信怎么写
2015/03/04 职场文书
从np.random.normal()到正态分布的拟合操作
2021/06/02 Python