首页 > 编程语言 >小程序之图片裁剪(圆形、矩形)

小程序之图片裁剪(圆形、矩形)

时间:2024-03-26 10:59:47浏览次数:13  
标签:cutHeight const 裁剪 value 圆形 console 矩形 cutWidth

这个裁剪方法可以裁剪圆形、矩形,可以二开,放心食用

先看效果图:

矩形的:

圆形的:

具体的方法:

组件的:

// cropper--index.vue


<template>
  <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 v-if="src" :style="{width:cutWidth +'px', height:cutHeight + 'px'}" class="fyj_movable_view" :x="x"
                    :y="y" direction="all" :scale="true" @change="movableChange" @scale="handleScale"></movable-view>
      <image class="fyj_photo" id="fyj_photo" :src="src" mode="widthFix"/>
    </movable-area>
    <!--</canvas>-->
    <view style="margin-top:20rpx; padding:0 20rpx;">
      <button class="pull-left" type="warn" size="mini" @click="getPhoto">选择照片/拍照</button>
      <button class="pull-right" type="primary" size="mini" @click="cut">裁剪</button>
      <view class="clearfix"></view>
    </view>
  </view>
</template>

<script setup>
import {ref, reactive, watch, nextTick, getCurrentInstance} from 'vue'

const {aspectRatio} = defineProps({
  // 这里定义了innerText属性,属性值可以在组件使用时指定
  //宽高比 TODO 这个要求裁剪框是矩形的,如果裁剪框是圆形的,这个属性宽高比一定得是1
  aspectRatio: {
    type: Number,
    default: 5 / 7,
  },
})

const screenWidth = ref(uni.getSystemInfoSync().windowWidth)
const canvasHeight = ref(300)
const x = ref(0)
const y = ref(0)
const src = ref('')
const cut_src = ref('')
const cutWidth = ref(0)
const cutHeight = ref(0)

const tempImage = ref('')

const {proxy} = getCurrentInstance()

const emits = defineEmits(['getTempFilePath'])
// 这里是一个自定义方法
//选择照片
const getPhoto = () => {
  const ctx = uni.createCanvasContext('myCanvas', proxy)
  let obj = uni.createSelectorQuery();
  uni.chooseImage({
    count: 1,
    sizeType: ['original', 'compressed'],
    sourceType: ['album', 'camera'],
    success(res) {
      //清空之前的剪切图
      emits('getTempFilePath', {cut_src: '', cutWidth: cutWidth.value, cutHeight: cutHeight.value})

      // tempFilePath可以作为img标签的src属性显示图片
      const tempFilePaths = res.tempFilePaths[0];
      src.value = tempFilePaths
      // 这个变量是为了下面圆形裁剪框使用的 可以结合一个配置项判断是否要使用
      tempImage.value = tempFilePaths
      cut_src.value = ''

      setTimeout(function () {
        // TODO 这里也可以换成小程序获取图片信息的那个api方法
        uni.createSelectorQuery().in(proxy).select('#fyj_photo').boundingClientRect(function (rect) {
          console.log(rect);
          console.log('图片的信息', rect.height);
          canvasHeight.value = rect.height
          setCut();
          // TODO 矩形裁剪框使用的是这个
          // ctx.drawImage(tempFilePaths, 0, 0, screenWidth.value, canvasHeight.value)
          // ctx.draw()

          // 放到上面去了,防止一开始拿不到
          // setCut();
          //确保不同大小的图片,切图不会变形
          x.value = 0
          y.value = 0
        }).exec()
      }, 100)
    }
  })
}

//获取图片高度 暂时没用到
// const getHeight = () => {
//   const query = uni.createSelectorQuery().in(proxy)
//   query.selectAll('#fyj_photo').boundingClientRect()
//   query.exec(function (rect) {
//     console.log(rect);
//     console.log(rect[0].height);
//     canvasHeight.value = rect[0].height
//     // TODO ...
//     ctx.drawImage(tempFilePaths[0], 0, 0, screenWidth.value, canvasHeight.value)
//     ctx.draw();
//     setCut();
//   })
// }

//裁剪框移动事件
const movableChange = debounce((e) => {
  console.log('裁剪框移动', e);
  x.value = e.detail.x
  y.value = e.detail.y


  // TODO 这部分可以抽成一个方法配合一个配置项 圆形裁剪框
  const ctx = uni.createCanvasContext('myCanvas', proxy)
  setTimeout(function () {
    // TODO 这里也可以换成小程序获取图片信息的那个api方法
    uni.createSelectorQuery().in(proxy).select('#fyj_photo').boundingClientRect(function (rect) {
      console.log(rect);
      console.log('图片的信息', rect.height);
      canvasHeight.value = rect.height
      setCut();


      // TODO 圆形裁剪框 裁剪圆形的图片
      // 开始一个新的路径
      ctx.save()
      ctx.beginPath();
      // 创建一个圆形路径
      ctx.arc((x.value + (cutWidth.value / 2)), (y.value + (cutWidth.value / 2)), cutWidth.value / 2, 0, Math.PI * 2, false);
      // 设置当前路径为剪切路径
      ctx.clip();

      // 再次绘制图片,只有在剪切路径内的部分会被绘制
      ctx.drawImage(tempImage.value, 0, 0, screenWidth.value, canvasHeight.value);
      ctx.restore();
      ctx.draw();

      // 这个放到上面去了,防止一开始拿不到
      // setCut();
      // TODO 圆形裁剪框时是不需要的  确保不同大小的图片,切图不会变形
      // x.value = 0
      // y.value = 0
      // TODO 防止第二次圆形绘制失效
      ctx.clearRect(0, 0, screenWidth.value, canvasHeight.value)
    }).exec()
  }, 100)
}, 500)

//截图
const cut = () => {
  console.log(cutHeight.value);
  uni.canvasToTempFilePath({
    // TODO 不管是绘制圆形还是矩形,这里的配置都是一样的
    x: x.value,
    y: y.value,
    width: cutWidth.value,
    height: cutHeight.value,
    destWidth: cutWidth.value,
    destHeight: cutHeight.value,
    canvasId: 'myCanvas',
    success(res) {
      console.log(res.tempFilePath);
      cut_src.value = res.tempFilePath
      emits('getTempFilePath', {cut_src: cut_src.value, cutWidth: cutWidth.value, cutHeight: cutHeight.value})
    }
  }, proxy)
}

//动态设置裁剪框大小,确定高度不得超过canvas的高度
const setCut = () => {
  // TODO 这里比较重要
  cutWidth.value = uni.getSystemInfoSync().windowWidth * 0.8
  cutHeight.value = uni.getSystemInfoSync().windowWidth * 0.8 / aspectRatio

  if (cutHeight.value - 4 > canvasHeight.value) {
    console.log(cutHeight.value);
    console.log(canvasHeight.value);
    cutHeight.value = canvasHeight.value - 4
    cutWidth.value = (canvasHeight.value - 4) * aspectRatio
  } else {
    cutWidth.value = uni.getSystemInfoSync().windowWidth * 0.8
    cutHeight.value = uni.getSystemInfoSync().windowWidth * 0.8 / aspectRatio
  }
  console.log('裁剪框的宽', cutWidth.value);
  console.log('裁剪框的高', cutHeight.value);
}

// 裁剪框缩放事件
const handleScale = debounce((e) => {
  console.log('裁剪框缩放', e);
  cutWidth.value = cutWidth.value * e.detail.scale
  cutHeight.value = cutWidth.value * e.detail.scale
}, 500)


// 防抖
function debounce(func, wait, immediate=false) {
  let timeout;

  return function executedFunction() {
    const context = this;
    const args = arguments;

    const later = function() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };

    const callNow = immediate && !timeout;

    clearTimeout(timeout);

    timeout = setTimeout(later, wait);

    if (callNow) func.apply(context, args);
  };
}

</script>


<style scoped lang="scss">
// TODO 隐藏画布可以吧注释放开
.fyj_canvas {
  //position: absolute;
  //left: 0;
  //top: -71vh;
  //z-index: -1;
  //opacity: 0;
}

.fyj_movable_area {
  width: 100%;
  height: auto;
  position: relative;
  background: rgba(0, 0, 0, 0.3);
  z-index: 99;
}

.fyj_movable_view {
  border: 2px dashed red;
  // TODO 圆形裁剪框时使用的
  border-radius: 50%;
}

.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;
}
</style>

 

使用组件:

// testCropper--index.vue


<template>
  <view>
    <!-- aspectRatio 剪裁图片的宽高比 -->
    <cropper :aspectRatio="1" @getTempFilePath="getCutsrc"></cropper>
    <view v-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"/>
    </view>
    <view v-if="cut_src" class="fyj_footer text-center">
      <button class="fyj_footerBtn fyj_sure" @click='sure'>确定</button>
    </view>
  </view>
</template>

<script setup>
import {ref} from 'vue'
import cropper from '../components/cropper/index.vue'

const cut_src = ref('');
const cutWidth = ref(0);
const cutHeight = ref(0);

const getCutsrc = (e) => {
  console.log('子组件的传值', e)
  cut_src.value = e.cut_src;
  cutWidth.value = e.cutWidth;
  cutHeight.value = e.cutHeight;
}

</script>


<style scoped lang="scss">
.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;
}
</style>

参考:

https://www.jb51.net/article/249152.htm

https://blog.csdn.net/hanjiepo/article/details/132428196

标签:cutHeight,const,裁剪,value,圆形,console,矩形,cutWidth
From: https://blog.csdn.net/qq_42238378/article/details/136975154

相关文章

  • 使用opnecv裁剪鼠标所选范围的图片
    使用opnecv裁剪鼠标所选范围的图片裁剪代码效果根据鼠标选择范围进行裁剪效果代码裁剪opencv实现裁剪很简单,确定左上角和右下角的坐标进行切片即可。代码importcv2#读取图片image=cv2.imread('blue_2.jpg')#定义裁剪区域的左上角和右下角坐标top_left......
  • 【蓝桥杯】(3.19矩形总面积)
    #include<iostream>#defineLLlonglongusingnamespacestd;intmain(){LLx1,y1,x2,y2,x3,y3,x4,y4;cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4;LLs1,s2,s;s1=(x2-x1)*(y2-y1);s2=(x4-......
  • 解决三维模型的立体裁剪的主要技术方法
    解决三维模型的立体裁剪的主要技术方法 三维模型的立体裁剪是指在三维空间中对物体进行裁剪,以便在渲染、动画和虚拟现实等应用中获得所需的效果。立体裁剪技术在计算机图形学和计算机辅助设计领域有着广泛的应用。本文将介绍三维模型立体裁剪的主要技术方法。 体素化......
  • Java 编程实例:相加数字、计算单词数、字符串反转、元素求和、矩形面积及奇偶判断
    Java如何相加两个数字相加两个数字示例intx=5;inty=6;intsum=x+y;System.out.println(sum);//打印x+y的和输出11解释首先,声明两个int类型的变量x和y,并分别赋值为5和6。然后,使用+运算符将x和y相加,并将结果赋给变量sum。最后,使用Sy......
  • Google Earth Engine——如何实现裁剪后研究区影像的批量下载(以NDVI为例)
    简介GEE云平台(GoogleEarthEngine)是一个强大的云平台,提供了丰富的地理数据和计算资源,用于进行地理数据分析和处理。在GEE平台上,可以实现对研究区影像的单景影像(以NDVI为例)的批量下载。下面是具体的过程:1.登录GEE云平台并初始化首先,需要登录GEE云平台(https://earthengine.g......
  • Android 圆形进度条ProgressBar实现固定进度
    原文:Android圆形进度条ProgressBar实现固定进度-Stars-One的杂货小窝之前遇到一个问题,发现Android里的圆形进度条无法固定一个进度,记录一下解决方法探究假设我们在xml中这样写:<?xmlversion="1.0"encoding="utf-8"?><FrameLayoutxmlns:android="http://schemas.and......
  • 【工程应用九】再谈基于离散夹角余弦相似度指标的形状匹配优化(十六角度量化+指令集加
    继去年上半年一鼓作气研究了几种不同的模版匹配算法后,这个方面的工作基本停滞了有七八个月没有去碰了,因为感觉已经遇到了瓶颈,无论是速度还是效率方面,以当时的理解感觉都到了顶了。年初,公司业务惨淡,也无心向佛,总要找点事情做一做,充实下自己,这里选择了前期一直想继续研究的基于......
  • 倾斜摄影三维模型的立体裁剪的问题分析
    倾斜摄影三维模型的立体裁剪的问题分析   倾斜摄影是一种利用斜视角进行拍摄和测量的技术,可以获得具有高精度的三维模型。然而,在生成三维模型的过程中,立体裁剪是一个重要的问题。立体裁剪是指将倾斜摄影的影像数据与地面数据进行匹配和融合,以生成真实而准确的三维模型。本......
  • ENVI CLASSIC进行影像裁剪
    影像裁剪的目的是将研究区以外的区域去除,经常是按照行政区划或研究区域的边界对图像进行裁剪,在基础数据生产中,还经常要做标准分副裁剪。按照ENVI的图像裁剪过程,可分为规则裁剪和不规则裁剪。一、规则裁剪1、在主菜单中,选择File→OpenImageFile,打开裁剪的图像2、在主菜单......
  • lc84 柱状图中最大的矩形
    给定数组H[n],表示柱状图中各个柱子的高度,每个柱子彼此相邻,且宽度为1。求该柱状图中,能够勾勒出来的矩形的最大面积。1<=n<=1e5;0<=H[i]<=1e4枚举每个柱子作为最短时能得到的最大矩形,尽量往两边延伸,取最小值即为答案。classSolution{public:intlargestRectangleArea(v......