微信小程序之裁剪图片成圆形的实现代码


Posted in Javascript onOctober 11, 2018

前言

最近在开发小程序,产品经理提了一个需求,要求微信小程序换头像,用户剪裁图片必须是圆形,也在github上看了一些例子,一般剪裁图片用的都是方形,所以自己打算写一个小组件,可以把图片剪裁成圆形,主要思路就是使用canvas绘图,把剪裁的图片绘制成圆形,另外剪裁图片的窗口还可以移动放大缩小,这个功能就用了微信组件movable-view,好了,该说的也说完了,下面咱们开始撸代码。

movable-view组件

可移动的视图容器,在页面中可以拖拽滑动

会有好多个属性,在这里不一一介绍,只说我们能用到的就可以。

我们用到的属性主要有:

1.direction:movable-view的移动方向,属性值有all、vertical、horizontal、none

2.scale:是否支持双指缩放,默认缩放手势生效区域是在movable-view内

3.scale-min 定义缩放倍数最小值

4.scale-max 定义缩放倍数最大值

5.bindchange 拖动过程中触发的事件,event.detail = {x: x, y: y, source: source},其中source表示产生移动的原因,值可为touch(拖动)、touch-out-of-bounds(超出移动范围)、out-of-bounds(超出移动范围后的回弹)、friction(惯性)和空字符串(setData)

6.bindscale 缩放过程中触发的事件,event.detail = {x: x, y: y, scale: scale},其中x和y字段在2.1.0之后开始支持返回

主要用到的就是这几个值

另外使用movable-view的时候必须在外边加一个movable-area的父元素,不然的话没有移动区域。

movable-view 的可移动区域,属性只有:

scale-area 当里面的movable-view设置为支持双指缩放时,设置此值可将缩放手势生效区域修改为整个movable-area,是个boolean值,默认false

截取区域的移动已经说完了,详情请看传送门

canvas绘图

画布。该组件是原生组件可以绘制图像,分享朋友圈生成海报就经常用到这个属性,就简单的说下:

在wxml中必须要有canvas这个标签,才可以绘制图像,而且要有canvas-id属性,代表canvas 组件的唯一标识符,
还有许多API我就不一一介绍了,底下用的API代码当中都会用注释。详情请看微信小程序画布API传送门

代码实现

1.首先是选择图片

wxml就是初始化一个按钮点击的时候选择图片,而且需要引入我们封装的截取图片组件,并把图片作为参数传进去,封装组件方法请看我另一篇文章组件封装

index.wxml

Tip: 必须把canvas放到引入剪裁组件的wxml中,否则绘制不成功,因为canvas是原生组件脱离在 WebView 渲染流程外。

<view class="container">
 <button wx:if="{{!imgSrc}}" bindtap="getImgurl"> 选择图片 </button>
 <view class="clip-box" wx:if="{{imgSrc}}">
  <ClipImg imgSrc="{{imgSrc}}"></ClipImg>
 </view>
</view>
<canvas canvas-id="myCanvas" style="position:absolute; width:100%;height:100%;border: 1px solid red;left: -9999px; top: -9999px;"></canvas>

index.json引入截取图片的组件

{
 "component": true,
 "usingComponents": {
  "ClipImg": "../../component/clipImg/clipImg"
 }
}

index.js上传图片显示

const app = getApp()

Page({
 data: {
 imgSrc: ''
 },
 //选择图片
 getImgurl: function () {
 wx.chooseImage({
  count: 1, // 默认9
  sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
  sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
  success: (res) => {
  // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
  const tempFilePaths = res.tempFilePaths;
  //启动上传等待中... 
  wx.showToast({ 
   title: '正在上传...', 
   icon: 'loading', 
   mask: true, 
   duration: 1000 
  }) 
  this.setData({
   imgSrc: res.tempFilePaths
  })
  }
 })
 },
 onLoad: function () {
 }
})

接下来就是剪裁图片组件的封装

首先是页面布局,也就是clipImg.wxml

<view class="clip">
 <image class="head-img" style="width:{{cropperW}}rpx;height:{{cropperH}}rpx" src="{{imageUrl}}"></image>
 <movable-area scale-area style="width:{{cropperW}}rpx;height:{{cropperH}}rpx">
  <movable-view bindchange="move" bindscale="scale" direction="all" scale scale-min="0.5" scale-max="1.8">
  </movable-view>
 </movable-area>
 <view class="btn">
  <text bindtap="cancel">取消</text>
  <text bindtap="getImageInfo">保存</text>
 </view>
</view>

大概就是这个样子

微信小程序之裁剪图片成圆形的实现代码

上边的圆就是截取就是截取框。

然后就是clipImg.js文件主要就是对图片截取的一些操作

Component({
 /**
 * 组件的属性列表
 */
 properties: {
 imgSrc: {
  type: 'String',
  value: ''
 }
 },
 /**
 * 组件的初始数据
 * imageUrl string 初始化图片
 * cropperW string 缩小图宽度
 * cropperH string 缩小图高度,
 * img_ratio string 图片比例,
 * IMG_W string 原图高度,
 * IMG_H string 原图高度,
 * left string 图片距离左边距离,
 * top string 图片距离上边距离,
 * clipW number 默认截取框
 */
 data: {
 imageUrl: '',
 cropperW: '',
 cropperH: '',
 img_ratio: '',
 IMG_W: '',
 IMG_H: '',
 left: '',
 top: '',
 clipW: 200
 },
 /**
 * 组件的方法列表
 */
 methods: {
 //点击取消
 cancel: function () {
  var myEventDetail = {} // detail对象,提供给事件监听函数
  var myEventOption = {} // 触发事件的选项
  this.triggerEvent('myevent', myEventDetail, myEventOption)
 },
 //拖拽事件
 move: function ({ detail }) {
  this.setData({
  left: detail.x * 2,
  top: detail.y * 2
  })
 },
 //缩放事件
 scale: function ({ detail }) {
  console.log(detail.scale)
  this.setData({
  clipW: 200 * detail.scale
  })
 },
 //生成图片
 getImageInfo: function () {
  wx.showLoading({
  title: '图片生成中...',
  })
  const img_ratio = this.data.img_ratio;
  //要截取canvas的宽
  const canvasW = (this.data.clipW / this.data.cropperW) * this.data.IMG_W
  //要截取canvas的高
  const canvasH = (this.data.clipW / this.data.cropperH) * this.data.IMG_H
  //要截取canvas到左边距离
  const canvasL = (this.data.left / this.data.cropperW) * this.data.IMG_W
  //要截取canvas到上边距离
  const canvasT = (this.data.top / this.data.cropperH) * this.data.IMG_H
  // 将图片写入画布
  const ctx = wx.createCanvasContext('myCanvas');
  //绘制图像到画布
  ctx.save(); // 先保存状态 已便于画完圆再用  
  ctx.beginPath(); //开始绘制 
  ctx.clearRect(0, 0, 1000, 1000)
  //先画个圆  
  ctx.arc(this.data.clipW / 2, this.data.clipW / 2, this.data.clipW / 2, 0, 2 * Math.PI, false)
  ctx.clip();//画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内 
  ctx.drawImage(this.data.imageUrl, canvasL, canvasT, canvasW, canvasH, 0, 0, this.data.clipW, this.data.clipW); // 推进去图片  
  ctx.restore(); //恢复之前保存的绘图上下文 恢复之前保存的绘图上下午即状态 可以继续绘制
  ctx.draw(true, () => {
  // 获取画布要裁剪的位置和宽度 
  wx.canvasToTempFilePath({
   x: 0,
   y: 0,
   width: this.data.clipW,
   height: this.data.clipW,
   destWidth: this.data.clipW,
   destHeight: this.data.clipW,
   quality: 0.5,
   canvasId: 'myCanvas',
   success: (res) => {
   wx.hideLoading()
   /**
    * 截取成功后可以上传的服务端直接调用
    * wx.uploadFile();
    */
   //成功获得地址的地方
   wx.previewImage({
    current: '', // 当前显示图片的http链接
    urls: [res.tempFilePath] // 需要预览的图片http链接列表
   })
   }
  })
  })
 }
 },
 ready: function () {
 this.setData({
  imageUrl: this.data.imgSrc[0]
 })
 //获取图片宽高
 wx.getImageInfo({
  src: this.data.imageUrl,
  success: (res) => {
  console.log('图片信息', res);
  //图片实际款高
  const width = res.width;
  const height = res.height;
  //图片宽高比例
  const img_ratio = width / height
  this.setData({
   img_ratio,
   IMG_W: width,
   IMG_H: height,
  })
  if (img_ratio >= 1) {
   //宽比较大,横着显示
   this.setData({
   cropperW: 750,
   cropperH: 750 / img_ratio,
   })
  } else {
   //竖着显示
   this.setData({
   cropperW: 750 * img_ratio,
   cropperH: 750
   })
  }
  } 
 })
 }
})

到现在为止一个截取图片就完成了,可能会有些问题,比如截取的图片的框没有居中,自己可以再次封装这个组件,因为现在已经适合我们公司自己项目了。我们来预览下。另外这个组件支持双指放大截取框来截取图片,不过微信开发者工具不能展示,自己可以把代码下载下来,在自己手机上扫码查看效果。

微信小程序之裁剪图片成圆形的实现代码

另外我把项目放到了github上边,希望小哥哥小姐姐们多多点赞,多多支持,有什么疑问可以在github上问我,谢谢。点赞的小哥哥小姐姐最可爱,哈哈哈。。。

项目地址链接描述

推荐:

感兴趣的朋友可以关注小编的微信公众号【码农那点事儿】,更多网页制作特效源码及学习干货哦!!!

总结

以上所述是小编给大家介绍的微信小程序之裁剪图片成圆形的实现代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
如何让easyui gridview 宽度自适应窗口改变及fitColumns应用
Jan 25 Javascript
Node.js中require的工作原理浅析
Jun 24 Javascript
JavaScript弹出窗口方法汇总
Aug 12 Javascript
BootStrap实现手机端轮播图左右滑动事件
Oct 13 Javascript
如何用js判断dom是否有存在某class的值
Feb 13 Javascript
Vue2.x中的Render函数详解
May 30 Javascript
vue中SPA单页面应用程序详解
Nov 07 Javascript
JavaScript内存泄漏的处理方式
Nov 20 Javascript
解决layui 表单元素radio不显示渲染的问题
Sep 04 Javascript
JavaScript switch语句使用方法简介
Dec 30 Javascript
解决vue elementUI中table里数字、字母、中文混合排序问题
Jan 07 Javascript
javascript实现移动端上传图片功能
Aug 18 Javascript
Vue中使用ElementUI使用第三方图标库iconfont的示例
Oct 11 #Javascript
css配合JavaScript实现tab标签切换效果
Oct 11 #Javascript
vue最简单的前后端交互示例详解
Oct 11 #Javascript
JavaScript中七种流行的开源机器学习框架
Oct 11 #Javascript
用Object.prototype.toString.call(obj)检测对象类型原因分析
Oct 11 #Javascript
使用vue 国际化i18n 实现多实现语言切换功能
Oct 11 #Javascript
详解Angular5/Angular6项目如何添加热更新(HMR)功能
Oct 10 #Javascript
You might like
PHP文件读写操作之文件写入代码
2011/01/13 PHP
Array of country list in PHP with Zend Framework
2011/10/17 PHP
CodeIgniter框架URL路由总结
2014/09/03 PHP
PHP直接修改表内容DataGrid功能实现代码
2015/09/24 PHP
PHP中__autoload和Smarty冲突的简单解决方法
2016/04/08 PHP
详解php伪造Referer请求反盗链资源
2019/01/24 PHP
使用laravel的migrate创建数据表的方法
2019/09/30 PHP
Yii框架多语言站点配置方法分析【中文/英文切换站点】
2020/04/07 PHP
不错的JS中变量相关的细节分析
2007/08/13 Javascript
javascript 类定义的4种方法
2009/09/12 Javascript
让alert不出现弹窗的两种方法
2014/05/18 Javascript
javascript正则表达式参数/g与/i及/gi的使用指南
2014/08/27 Javascript
浅谈javascript中关于日期和时间的基础知识
2016/07/13 Javascript
jquery实现手机端单店铺购物车结算删除功能
2017/02/22 Javascript
vue中动态设置meta标签和title标签的方法
2018/07/11 Javascript
Vue头像处理方案小结
2018/07/26 Javascript
使用javascript做时间倒数读秒功能的实例
2019/01/23 Javascript
Vue v-for循环之@click点击事件获取元素示例
2019/11/09 Javascript
Python操作Word批量生成文章的方法
2015/07/28 Python
详解pandas库pd.read_excel操作读取excel文件参数整理与实例
2019/02/17 Python
基于Python获取城市近7天天气预报
2019/11/26 Python
Python2.x与3​​.x版本有哪些区别
2020/07/09 Python
Selenium webdriver添加cookie实现过程详解
2020/08/12 Python
Belle Maison倍美丛官网:日本千趣会旗下邮购网站
2016/07/22 全球购物
英国第二大营养品供应商:Vitabiotics
2016/10/01 全球购物
英国马匹装备和马术用品购物网站:Equine Superstore
2019/03/03 全球购物
澳大利亚最大的在线美发和美容零售商之一:My Hair Care & Beauty
2019/08/24 全球购物
写给老婆的检讨书
2014/02/21 职场文书
大宝sod蜜广告词
2014/03/21 职场文书
公司委托书格式范本
2014/09/16 职场文书
公司总经理岗位职责
2015/04/01 职场文书
2015国庆节66周年标语
2015/07/30 职场文书
莫言获奖感言(全文)
2015/07/31 职场文书
《用字母表示数》教学反思
2016/02/17 职场文书
职工的安全责任书范文!
2019/07/02 职场文书
python神经网络ResNet50模型
2022/05/06 Python