微信小程序 实现上传图片前裁剪功能

news/2024/7/20 2:39:17 标签: 微信小程序, 小程序

前言

        技术支持: wx-cropper 裁剪

        总体思路是:安装完wx-cropper之后就它当成组件使用。在使用页面的地方引入组件就行。上传图片的逻辑不变,在 通过wx.chooseMedia() Api 拿到图片之后传递给子组件,子组件在拿到图片进行裁剪处理等操作之后,在把图片传递给父组件,父组件在拿到处理之后的图片,在进行自己之后的逻辑操作。简单来说就是------父组件上传图片-->子组件拿到图片进行处理-->处理的图片给父组件-->自己的逻辑操作

一. 引入wx-cropper

npm i @dw/wx-cropper

安装wx-cropper之后构建npm

二. 在需要使用的页面上引入

{
  "usingComponents": {
    "my-cropper": "@dw/wx-cropper"
  }
}

 三. 示例

        1. wxml代码

<button catchtap="handleuploadimg">上传图片</button>

<block wx:for="{{ fileList }}" wx:key="*this">
  <image src="{{ item }}" mode=""/>
</block>

<view class="layers" wx:if="{{cjtp}}">
    <my-cropper bind:close="hideCut" cutRatio="{{cutRatio}}" imageSrc="{{imageSrc}}" />
</view>

        2. wxss样式 

                这个是需要把裁剪功能组件覆盖到当前页面上

/* pages/upload/upload.wxss */
.layers{
  width: 100vw;
  height: 100vh;
  background-color: #00000080;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 10000000;
}

 

        3. js代码

                当选择完图片时,显示裁剪功能,以及把上传的图片传给组件。当用户裁剪完图片之后,会通过组件getImageInfo方法处理图片之后,在通过子组件向父组件传值的方法,把裁剪处理完之后图片传递给父组件 _this.triggerEvent('close', img);

// pages/upload/upload.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    fileList: [], //上传图片集合
    base64List: [], //base64集合
    delFileArr:[],  //删除的附件集合
    imgWidthslot: 0,
    imgHeightslot: 0,
    //裁剪信息
    cjtp: false,     //裁剪信息 这个控制裁剪功能的现实和隐藏
    cutRatio:0.75,  //裁剪比例
    imageSrc:'',    //个人图片
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {

  },
  // 上传图片
  handleuploadimg() {
    wx.chooseMedia({
      count: 1,
      mediaType: ['image'],
      sourceType: ['camera', 'album'],
      success: (res) => {
        // this.setData({
        //   fileList: res.tempFiles
        // })
        var tempFilePaths = res.tempFiles;
        for (let i in tempFilePaths) {
          let imagePath = tempFilePaths[i].tempFilePath; //原图的路径
          let size = tempFilePaths[i].size;      //原图大小
            //this.setData({
             // imageSrc:imagePath,
              //cjtp:true,
            //})
            //判断是否需要压缩
           if(size > this.data.size){
              this.setCanvasLoad(imagePath);
           }else{
            this.setData({
              imageSrc:imagePath,
              cjtp:true,
            })
          }
          
        }
      }
    })
  },
// 压缩图片
setCanvasLoad(obj){
    let imagePath = obj; //原图的路径
      const ctx = wx.createCanvasContext('myfirstCanvasSlot',this);
      let that = this;
      wx.showLoading({
        title: '图片压缩中...',
        mask: true
      }) //不需要你可以删掉
      // console.log(imagePath,'原图的路径')
      wx.getImageInfo({
        src:imagePath,
        success:(res)=>{
          // console.log(res,'获取图片的属性')
          // 图片原始尺寸
          let originWidth = res.width;
          let originHeight = res.height;
          // 最大尺寸限制,可通过设置宽高来实现图片压缩程度
          let maxWidth = 1920,
              maxHeight = 800;
          // 目标尺寸
          let targetWidth = originWidth,
              targetHeight = originHeight;
          // 图片尺寸超过200x150的限制
          if(originWidth > maxWidth || originHeight > maxHeight) {
              if(originWidth / originHeight > maxWidth / maxHeight) {
                  // 更宽,按照宽度限定尺寸
                  targetWidth = maxWidth;
                  targetHeight = Math.round(maxWidth * (originHeight / originWidth));
              } else {
                  targetHeight = maxHeight;
                  targetWidth = Math.round(maxHeight * (originWidth / originHeight));
              }
          }
          // canvas对图片进行缩放
          this.setData({
              imgWidthslot: targetWidth,
              imgHeightslot: targetHeight
          })

          // 压缩图片(绘制图像到画布)
          ctx.drawImage(imagePath,0,0,targetWidth,targetHeight);
          console.log(this.data.imgWidth)

          ctx.draw(false, ()=>{
            setTimeout(()=>{
              // canvas导出为图片路径
              wx.canvasToTempFilePath({
                canvasId: 'myfirstCanvasSlot',
                fileType: 'png', //支持jpg或png
                quality: 0.92, //图片质量
                success:(res1)=> {
                    wx.hideLoading();
                    // console.log(targetWidth,targetHeight,'targetHeight')
                    let compressedPath = res1.tempFilePath;
                    //将图片转化为base64
                    this.setData({
                      imageSrc:compressedPath,
                      cjtp:true,
                    })
                },
                fail:(res1)=>{
                  // console.log('图片压缩失败',res)
                  wx.hideLoading()
                  wx.showModal({
                    content: '图片压缩失败',
                    showCancel:false
                  })
                }
              },that)
            },200)
             
          })
        },
        fail: (res) => {
          wx.hideLoading()
          // console.log(res,'获取图片的属性失败');
          wx.showModal({
            content: '图片压缩失败',
            showCancel:false
          })
        }
      })
  },
  
  //关闭裁剪
  hideCut(e){
    let obj = e.detail;
    let fileList = this.data.fileList;
    let base64List = this.data.base64List;
    //是否已经截取
    if(obj){
      console.log('------obj', obj)
      wx.showLoading({
        title: '裁剪中',
      })
      fileList = [ obj.path ]
      wx.getFileSystemManager().readFile({
        filePath: obj.path,
        encoding: "base64",
        success: (res) => {
          
          wx.hideLoading(); //不需要你可以删掉
          base64List = [res.data]
          this.setData({
            base64List: base64List,
            fileList: fileList,
          })

          console.log('-----res-----', this.data.base64List, this.data.fileList)
        },
        fail: (res) => {

          wx.hideLoading(); //不需要你可以删掉
          wx.showModal({
            content: '图片裁剪失败',
            showCancel:false
          })
        }
      })
    }
    this.setData({
      cjtp:false,
    })
  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})

父组件会通过hideCut方法 来拿到子组件传递过来的图片,然后在回显到页面上。 


http://www.niftyadmin.cn/n/5263071.html

相关文章

软考机考考试第一批经验分享

由于机考的特殊性&#xff0c;考试环境与传统笔试环境有所不同。下面是与考试环境相关的总结&#xff1a; 草稿纸&#xff1a;考场提供足够数量的草稿纸&#xff0c;每位考生都会分发一张白纸作为草稿纸。在草稿纸上需要写上准考证号。如果不够用&#xff0c;可以向监考老师再次…

Jmeter实现服务器端后台接口性能测试!

实现目的 在进行服务器端后台接口性能测试时&#xff0c;需要连接到Linux服务器端&#xff0c;然后通过命令调用socket接口&#xff0c;这个过程就需要用到jmeter的SSH Command取样器实现了。 脚本实现 设置CSV Data Set ConFig配置元件&#xff0c;参数化测试数据 设置SSH…

PHP 实现 word/excel/ppt 转换为 PDF

OpenOffice OpenOffice 是一套开源跨平台的办公软件&#xff0c;由许多自由软件人士共同来维持&#xff0c;让大家能在 Microsoft Office 之外&#xff0c;还能有免费的 Office 可以使用。 OpenOffice 与微软的办公软件套件兼容&#xff0c;能将 doc、xls、ppt 等文件转换为 …

数据结构与算法之美学习笔记:35 | Trie树:如何实现搜索引擎的搜索关键词提示功能?

目录 前言什么是“Trie 树”&#xff1f;如何实现一棵 Trie 树&#xff1f;Trie 树真的很耗内存吗&#xff1f;Trie 树与散列表、红黑树的比较解答开篇内容小结 前言 本节课程思维导图&#xff1a; 搜索引擎的搜索关键词提示功能&#xff0c;我想你应该不陌生吧&#xff1f;为…

SpringBoot整合Lucene实现全文检索【详细步骤】【附源码】

笑小枫的专属目录 1. 项目背景2. 什么是Lucene3. 引入依赖&#xff0c;配置索引3.1 引入Lucene依赖和分词器依赖3.2 表结构和数据准备3.3 创建索引3.4 修改索引3.5删除索引 4. 数据检索4.1 基础搜索4.2 一个关键词&#xff0c;在多个字段里面搜索4.3 搜索结果高亮显示4.4 分页检…

MyBatisPlus通用方法测试

1、MyBatisPlus的基本使用方式 Mapper层 继承MyBatisPlus提供的BaseMapper即可。 Repository public interface UserMapper extends BaseMapper<User> { }Service层 接口继承IService&#xff0c;实现类继承ServiceImpl<M,E>即可。 public interface UserServic…

C++项目引入依赖_例jsoncpp(MAC/CLion)

1、git clone jsoncpp到本地 jsoncpp github地址&#xff1a;https://github.com/open-source-parsers/jsoncpp/tree/master 2、编译生成 lib 文件 进入jsoncpp文件目录 # 进入 jsoncpp 目录&#xff0c;创建一个新的子目录来存放编译输出&#xff1a; mkdir build &&a…

ShardingSphere数据分片之读写分离

1、概述 读写分离是一种常见的数据库架构&#xff0c;它将数据库分为主从库&#xff0c;一个主库&#xff08;Master&#xff09;用于写数据&#xff0c;多个从库&#xff08;Slave&#xff09;进行轮询读取数据的过程。主从库之间通过某种通讯机制进行数据的同步。 所以&…