Skip to content

Commit 1876fc3

Browse files
fix: 🐛 修复多个 ImgCropper 存在时生成图片异常的问题
1 parent 5a3f85d commit 1876fc3

3 files changed

Lines changed: 81 additions & 54 deletions

File tree

docs/component/img-cropper.md

Lines changed: 70 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
## 基本用法
66

7-
图片裁剪组件需要绑定 `v-model` 来控制组件的显示与隐藏,通过属性 `img-src` 控制展示的图片资源位,也可以通过函数 `resetImg` 来控制组件图片的初始化。进入组件后,可以对图片进行拖拽、双指缩放、旋转等操作监听 `confirm` 事件获取选中值
7+
图片裁剪组件需要绑定 `v-model` 来控制组件的显示与隐藏,通过属性 `img-src` 控制展示的图片资源。进入组件后,可以对图片进行拖拽、双指缩放、旋转等操作监听 `confirm` 事件获取裁剪结果
88

9-
> *注意:在使用组件时,最好在一个新页面中使用图片裁剪组件,图片裁剪保持`show`为true,完成裁剪时,返回上一页*
9+
> *注意:建议在新页面中使用图片裁剪组件,保持 `show` 为 true,完成裁剪后返回上一页*
1010
1111
```html
1212
<wd-img-cropper
@@ -55,55 +55,45 @@ function handleCancel(event) {
5555
}
5656
```
5757

58-
## Attributes
59-
60-
| 参数 | 说明 | 类型 | 可选值 | 默认值| 最低版本 |
61-
|-----|------|-----|-------|-------|--------|
62-
| v-model | 打开图片裁剪组件 | boolean | - | false | - |
63-
| img-src | 图片资源链接 | string | - | - | - |
64-
| img-width | 截屏预览图片的初始宽度; `1、设置宽度不设置高度,按照宽度等比缩放;2、如果都不设置,预览时图片大小会根据裁剪框大小进行等比缩放,进行锁边处理;`; string 类型只支持 % 单位,number 类型时单位为 px | number / string | - | - | - |
65-
| img-height | 截屏预览图片的初始高度; `1、设置高度不设置宽度,按照高度等比缩放;2、如果都不设置,预览时图片大小会根据裁剪框大小进行等比缩放,进行锁边处理;`; string 类型只支持 % 单位,number 类型时单位为 px | number / string | - | - | - |
66-
| disabled-rotate | 禁止图片旋转 | boolean | - | false | - |
67-
| export-scale | 设置导出图片尺寸 | number | - | 2 | - |
68-
| max-scale | 最大缩放倍数 | number | - | 3 | - |
69-
| cancel-button-text | 取消按钮文案 | string | - | 取消 | - |
70-
| confirm-button-text | 确认按钮文案 | string | - | 完成 | - |
71-
| quality | 生成的图片质量 [wx.canvasToTempFilePath属性介绍](https://developers.weixin.qq.com/miniprogram/dev/api/canvas/wx.canvasToTempFilePath.html#%E5%8F%82%E6%95%B0) | number | 0/1 | 1 | - |
72-
| file-type | 目标文件的类型,[wx.canvasToTempFilePath属性介绍](https://developers.weixin.qq.com/miniprogram/dev/api/canvas/wx.canvasToTempFilePath.html#%E5%8F%82%E6%95%B0) | string | - | png | - |
73-
| aspect-ratio | 裁剪框宽高比,格式为 width:height | string | - | 1:1 | $LOWEST_VERSION$ |
58+
## 自定义裁剪比例
7459

75-
## Events
60+
通过 `aspect-ratio` 属性可以设置裁剪框的宽高比,格式为 `width:height`
7661

77-
| 事件名称 | 说明 | 参数 | 最低版本 |
78-
|---------|-----|-----|---------|
79-
| confirm | 完成截图时触发 | `{tempFilePath, width, height}` 分别为生成文件的临时路径 (本地路径)、生成图片宽、生成图片高| - |
80-
| cancel | 当取消截图时触发 | - | - |
81-
| imgloaderror | 当图片加载错误时触发 | `{err} `| - |
82-
| imgloaded | 当图片加载完成时触发 | `{res}` | - |
62+
### 3:2 适合拍照
8363

84-
## Methods
64+
```html
65+
<wd-img-cropper
66+
v-model="show"
67+
:img-src="src"
68+
aspect-ratio="3:2"
69+
@confirm="handleConfirm"
70+
@cancel="handleCancel"
71+
>
72+
</wd-img-cropper>
73+
```
8574

86-
对外暴露函数
75+
### 16:9 影视比例
8776

88-
| 事件名称 | 说明 | 参数 | 最低版本 |
89-
|--------|------|-----|---------|
90-
| setRoate | 设置图片旋转角度 | deg (设置的旋转角度)| - |
91-
| resetImg | 重置图片的角度、缩放、位置 | - | - |
92-
93-
## 外部样式类
77+
```html
78+
<wd-img-cropper
79+
v-model="show"
80+
:img-src="src"
81+
aspect-ratio="16:9"
82+
@confirm="handleConfirm"
83+
@cancel="handleCancel"
84+
>
85+
</wd-img-cropper>
86+
```
9487

95-
| 类名 | 说明 | 最低版本 |
96-
|-----|------|--------|
97-
| custom-class | 根节点样式 | - |
88+
### 16:10 这么阔 很有型
9889

99-
## 基本用法
90+
16:10 的显示比例非常适合展示风景照片或者电影海报等宽屏内容。
10091

10192
```html
102-
<!-- 设置3:2的裁剪框 -->
10393
<wd-img-cropper
10494
v-model="show"
10595
:img-src="src"
106-
aspect-ratio="3:2"
96+
aspect-ratio="16:10"
10797
@confirm="handleConfirm"
10898
@cancel="handleCancel"
10999
>
@@ -171,3 +161,44 @@ async function handleConfirmUpload(event) {
171161
}
172162
}
173163
```
164+
165+
## Attributes
166+
167+
| 参数 | 说明 | 类型 | 可选值 | 默认值| 最低版本 |
168+
|-----|------|-----|-------|-------|--------|
169+
| v-model | 打开图片裁剪组件 | boolean | - | false | - |
170+
| img-src | 图片资源链接 | string | - | - | - |
171+
| img-width | 截屏预览图片的初始宽度; `1、设置宽度不设置高度,按照宽度等比缩放;2、如果都不设置,预览时图片大小会根据裁剪框大小进行等比缩放,进行锁边处理;`; string 类型只支持 % 单位,number 类型时单位为 px | number / string | - | - | - |
172+
| img-height | 截屏预览图片的初始高度; `1、设置高度不设置宽度,按照高度等比缩放;2、如果都不设置,预览时图片大小会根据裁剪框大小进行等比缩放,进行锁边处理;`; string 类型只支持 % 单位,number 类型时单位为 px | number / string | - | - | - |
173+
| disabled-rotate | 禁止图片旋转 | boolean | - | false | - |
174+
| export-scale | 设置导出图片尺寸 | number | - | 2 | - |
175+
| max-scale | 最大缩放倍数 | number | - | 3 | - |
176+
| cancel-button-text | 取消按钮文案 | string | - | 取消 | - |
177+
| confirm-button-text | 确认按钮文案 | string | - | 完成 | - |
178+
| quality | 生成的图片质量 [wx.canvasToTempFilePath属性介绍](https://developers.weixin.qq.com/miniprogram/dev/api/canvas/wx.canvasToTempFilePath.html#%E5%8F%82%E6%95%B0) | number | 0/1 | 1 | - |
179+
| file-type | 目标文件的类型,[wx.canvasToTempFilePath属性介绍](https://developers.weixin.qq.com/miniprogram/dev/api/canvas/wx.canvasToTempFilePath.html#%E5%8F%82%E6%95%B0) | string | - | png | - |
180+
| aspect-ratio | 裁剪框宽高比,格式为 width:height | string | - | 1:1 | $LOWEST_VERSION$ |
181+
182+
## Events
183+
184+
| 事件名称 | 说明 | 参数 | 最低版本 |
185+
|---------|-----|-----|---------|
186+
| confirm | 完成截图时触发 | `{tempFilePath, width, height}` 分别为生成文件的临时路径 (本地路径)、生成图片宽、生成图片高| - |
187+
| cancel | 当取消截图时触发 | - | - |
188+
| imgloaderror | 当图片加载错误时触发 | `{err} `| - |
189+
| imgloaded | 当图片加载完成时触发 | `{res}` | - |
190+
191+
## Methods
192+
193+
对外暴露函数
194+
195+
| 事件名称 | 说明 | 参数 | 最低版本 |
196+
|--------|------|-----|---------|
197+
| setRoate | 设置图片旋转角度 | deg (设置的旋转角度)| - |
198+
| resetImg | 重置图片的角度、缩放、位置 | - | - |
199+
200+
## 外部样式类
201+
202+
| 类名 | 说明 | 最低版本 |
203+
|-----|------|--------|
204+
| custom-class | 根节点样式 | - |

src/pages/imgCropper/Index.vue

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!--
22
* @Author: weisheng
33
* @Date: 2023-09-20 11:10:41
4-
* @LastEditTime: 2025-03-25 22:59:47
4+
* @LastEditTime: 2025-03-26 09:55:00
55
* @LastEditors: weisheng
66
* @Description:
77
* @FilePath: /wot-design-uni/src/pages/imgCropper/Index.vue
@@ -32,7 +32,7 @@
3232

3333
<demo-block title="自定义裁剪比例" style="text-align: center">
3434
<view class="profile-grid">
35-
<view v-for="(ratio, index) in ['1:1', '3:2', '16:9']" :key="index" class="profile-item">
35+
<view v-for="(ratio, index) in ['3:2', '16:9', '16:10']" :key="index" class="profile-item">
3636
<wd-img-cropper
3737
v-model="showCustom[index]"
3838
:img-src="srcCustom[index]"
@@ -45,7 +45,7 @@
4545
</view>
4646
<wd-img
4747
v-if="imgSrcCustom[index]"
48-
:width="ratio === '1:1' ? '200px' : '300px'"
48+
width="300px"
4949
:height="getHeight(ratio)"
5050
:src="imgSrcCustom[index]"
5151
mode="aspectFit"
@@ -262,13 +262,7 @@ function getHeight(ratio: string): string {
262262
position: relative;
263263
}
264264
265-
.profile-item:first-child .img {
266-
width: 200px;
267-
height: 200px;
268-
border-radius: 50%;
269-
}
270-
271-
.profile-item:nth-child(2) .img {
265+
.profile-item:nth-child(1) .img {
272266
height: 200px;
273267
}
274268
</style>

src/uni_modules/wot-design-uni/components/wd-img-cropper/wd-img-cropper.vue

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@
4848
</view>
4949
<!-- 绘制的图片canvas -->
5050
<canvas
51-
canvas-id="wd-img-cropper-canvas"
52-
id="wd-img-cropper-canvas"
51+
:canvas-id="canvasId"
52+
:id="canvasId"
5353
class="wd-img-cropper__canvas"
5454
:disable-scroll="true"
5555
:style="`width: ${Number(canvasWidth) * canvasScale}px; height: ${Number(canvasHeight) * canvasScale}px;`"
@@ -80,10 +80,12 @@ export default {
8080
import wdIcon from '../wd-icon/wd-icon.vue'
8181
import wdButton from '../wd-button/wd-button.vue'
8282
import { computed, getCurrentInstance, ref, watch } from 'vue'
83-
import { addUnit, objToStyle } from '../common/util'
83+
import { addUnit, objToStyle, uuid } from '../common/util'
8484
import { useTranslate } from '../composables/useTranslate'
8585
import { imgCropperProps, type ImgCropperExpose } from './types'
8686
87+
const canvasId = ref<string>(`cropper${uuid()}`) // canvas 组件的唯一标识符
88+
8789
// 延时动画设置
8890
let CHANGE_TIME: any | null = null
8991
// 移动节流
@@ -373,7 +375,7 @@ function computeImgSize() {
373375
*/
374376
function initCanvas() {
375377
if (!ctx.value) {
376-
ctx.value = uni.createCanvasContext('wd-img-cropper-canvas', proxy)
378+
ctx.value = uni.createCanvasContext(canvasId.value, proxy)
377379
}
378380
}
379381
@@ -575,7 +577,7 @@ function canvasToImage() {
575577
destHeight: Math.round(cutHeight.value * exportScale),
576578
fileType,
577579
quality,
578-
canvasId: 'wd-img-cropper-canvas',
580+
canvasId: canvasId.value,
579581
success: (res: any) => {
580582
const result = { tempFilePath: res.tempFilePath, width: cutWidth.value * exportScale, height: cutHeight.value * exportScale }
581583
// #ifdef MP-DINGTALK

0 commit comments

Comments
 (0)