当前位置 : 主页 > 网络编程 > JavaScript >

微信小程序实现照片裁剪

来源:互联网 收集:自由互联 发布时间:2023-01-18
本文实例为大家分享了微信小程序实现照片裁剪的具体代码,供大家参考,具体内容如下 前段时间用小程序的canvas、movable-area、movable-view封装了一个按比例裁剪照片的组件,无需引用任

本文实例为大家分享了微信小程序实现照片裁剪的具体代码,供大家参考,具体内容如下

前段时间用小程序的canvas、movable-area、movable-view封装了一个按比例裁剪照片的组件,无需引用任何插件。废话不多说,直接贴代码:

组件代码

1.cut_photo.json

{
  "component": true
}

2.cut_photo.wxml

<view>
  <canvas class="fyj_canvas" canvas-id="myCanvas" style="width:100%;height:{{canvasHeight}}px">
    <movable-area class="fyj_movable_area text-center hidden" style="width:100%;height:{{canvasHeight}}px;">
      <movable-view wx:if="{{src}}" style="width:{{cutWidth}}px;height:{{cutHeight}}px" class="fyj_movable_view"
        x="{{x}}"
        y="{{y}}"
        direction="all"
        bindchange="movableChange"
      ></movable-view>
      <image  class="fyj_photo" id="fyj_photo" src="{{src}}" mode="widthFix"></image>
    </movable-area>
  </canvas>
  <view style="margin-top:20rpx;padding:0 20rpx;">
    <button class="pull-left" type="warn" size="mini" bindtap="getPhoto">选择照片/拍照</button>
    <button class="pull-right" type="primary" size="mini" bindtap="cut">裁剪</button>
    <view class="clearfix"></view>
  </view>
</view>

3.cut_photo.js

const app = getApp()
Component({
  options: {
    //multipleSlots: true // 在组件定义时的选项中启用多slot支持
  },
  properties: {
    // 这里定义了innerText属性,属性值可以在组件使用时指定
    //宽高比
    aspectRatio: {
      type: Number,
      value: 5/7, 
    }
  },
  data: {
    screenWidth: wx.getSystemInfoSync().windowWidth,
    canvasHeight: 300,
    x: 0,
    y: 0,
    src: '',
    cut_src: '',
    cutWidth: 0,
    cutHeight: 0
  },
  attached: function () {
    
  },
  methods: {
    // 这里是一个自定义方法
    //选择照片
    getPhoto: function () {
      const $this = this;
      const ctx = wx.createCanvasContext('myCanvas',this)
      var obj = wx.createSelectorQuery();
      wx.chooseImage({
        count: 1,
        sizeType: ['original', 'compressed'],
        sourceType: ['album', 'camera'],
        success(res) {
          //清空之前的剪切图
          $this.triggerEvent('getTempFilePath', { cut_src: '', cutWidth: $this.data.cutWidth, cutHeight: $this.data.cutHeight })
          // tempFilePath可以作为img标签的src属性显示图片
          const tempFilePaths = res.tempFilePaths[0];
          $this.setData({
            src: tempFilePaths,
            cut_src: '',
          });
          setTimeout(function () {
            wx.createSelectorQuery().in($this).select('#fyj_photo').boundingClientRect(function (rect) {
              console.log(rect);
              console.log(rect.height);
              $this.setData({
                canvasHeight: rect.height
              })
              ctx.drawImage(tempFilePaths, 0, 0, $this.data.screenWidth, $this.data.canvasHeight)
              ctx.draw();
              $this.setCut();
              //确保不同大小的图片,切图不会变形
              $this.setData({
                x: 0,
                y: 0
              });
            }).exec()
          }, 100)
          

        }
      })
        
    },
    //获取图片高度
    // getHeight:function(){
    //   const query = wx.createSelectorQuery().in(this)
    //   query.selectAll('#fyj_photo').boundingClientRect()
    //   query.exec(function (rect) {
    //     console.log(rect);
    //     console.log(rect[0].height);
    //     $this.setData({
    //       canvasHeight: rect[0].height
    //     })
    //     ctx.drawImage(tempFilePaths[0], 0, 0, $this.data.screenWidth, $this.data.canvasHeight)
    //     ctx.draw();
    //     $this.setCut();
    //   })
    // },
    //裁剪框移动事件
    movableChange: function (e) {
      console.log(e.detail);
      this.setData({
        x: e.detail.x,
        y: e.detail.y
      })
    },
    //截图
    cut: function () {
      const $this = this;
      console.log($this.data.cutHeight);
      wx.canvasToTempFilePath({
        x: $this.data.x,
        y: $this.data.y,
        width: $this.data.cutWidth,
        height: $this.data.cutHeight,
        destWidth: $this.data.cutWidth,
        destHeight: $this.data.cutHeight,
        canvasId: 'myCanvas',
        success(res) {
          console.log(res.tempFilePath);
          $this.setData({
            cut_src: res.tempFilePath
          })
          $this.triggerEvent('getTempFilePath', { cut_src: $this.data.cut_src, cutWidth: $this.data.cutWidth, cutHeight: $this.data.cutHeight})
        }
      },this)
    },
    //动态设置裁剪框大小,确定高度不得超过canvas的高度
    setCut: function () {
      const $this = this;
      this.setData({
        cutWidth: wx.getSystemInfoSync().windowWidth * 0.8,
        cutHeight: wx.getSystemInfoSync().windowWidth * 0.8/this.data.aspectRatio
      })
      if (this.data.cutHeight - 4 > this.data.canvasHeight) {
        console.log($this.data.cutHeight);
        console.log($this.data.canvasHeight);
        this.setData({
          cutHeight: this.data.canvasHeight - 4,
          cutWidth: (this.data.canvasHeight - 4)*this.data.aspectRatio
        })
      } else {
        this.setData({
          cutWidth: wx.getSystemInfoSync().windowWidth * 0.8,
          cutHeight: wx.getSystemInfoSync().windowWidth * 0.8/this.data.aspectRatio
        })
      }
      console.log($this.data.cutWidth);
      console.log($this.data.cutHeight);
    },
  }
})

4.cut_photo.wxss

.fyj_movable_area{width:100%;height:auto;position: relative;background:rgba(0,0,0,0.3)}
.fyj_movable_view{border:2px dashed #fff}
.fyj_photo{width:100%;}
.fyj_footer{margin-top:20rpx 0;}
.fyj_footerBtn{width:100%;display: inline-block;color:#fff;border-radius: 0;font-size:32rpx;}
.fyj_sure{background: #fc6b47;}
.pull-left{float:left;}
.pull-right{float:right}
.clearfix{clear:both}
.text-center{text-align: center}

引用页代码

1.page.json

{
  "navigationBarTitleText": "选择照片",
  "usingComponents": {
    "cut-photo": "/pages/cut_photo/cut_photo"
  }
}

2.page.wxml

<view>
<!-- aspectRatio 剪裁图片的宽高比 -->
  <cut-photo aspectRatio="0.5" bindgetTempFilePath="getCutsrc"></cut-photo>
  <view wx:if="{{cut_src}}" class="fyj_cutDiv text-center">
    <image style="width:{{cutWidth}}px;height:{{cutHeight}}px" class="fyj_cut_photo" src="{{cut_src}}" mode="widthFix"></image>
  </view>
  <view wx:if="{{cut_src}}"  class="fyj_footer text-center">
    <button class="fyj_footerBtn fyj_sure" bindtap='sure'>确定</button>
  </view>
</view>

3.page.js

const app = getApp()
Page({

  /**
   * 页面的初始数据
   */
  data: {
    cut_src:'',
    cutWidth:0,
    cutHeight:0,
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
   
  },
  getCutsrc:function(e){
    console.log(e);
    this.setData({
      cut_src: e.detail.cut_src,
      cutWidth: e.detail.cutWidth,
      cutHeight: e.detail.cutHeight

    })
  }
})

4.page.wxss

.fyj_footer{margin-top:20rpx 0;}
.fyj_footerBtn{width:100%;display: inline-block;color:#fff;border-radius: 0;font-size:32rpx;}
.fyj_sure{background: #fc6b47;}
.fyj_cutDiv{margin:20rpx 0;}

大概思路

将canvas跟movable-area重合,通过movable-view来确定裁剪区域。为了确保图片加载不变形,选择完图片后,需要动态设置canvas、movable-area的高度及movable-view的宽高。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自由互联。

网友评论