优化
This commit is contained in:
@@ -99,11 +99,11 @@ class Page {
|
|||||||
* @returns 视图高度
|
* @returns 视图高度
|
||||||
*/
|
*/
|
||||||
getViewHeight() {
|
getViewHeight() {
|
||||||
// #ifdef H5
|
// #ifndef APP
|
||||||
return uni.getWindowInfo().windowHeight;
|
return uni.getWindowInfo().windowHeight;
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifndef H5
|
// #ifdef APP
|
||||||
const { screenHeight } = uni.getWindowInfo();
|
const { screenHeight } = uni.getWindowInfo();
|
||||||
|
|
||||||
let h = screenHeight;
|
let h = screenHeight;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/parser": "^7.27.5",
|
"@babel/parser": "^7.27.5",
|
||||||
"@babel/types": "^7.27.6",
|
"@babel/types": "^7.27.6",
|
||||||
"@cool-vue/ai": "^1.1.4",
|
"@cool-vue/ai": "^1.1.5",
|
||||||
"@cool-vue/vite-plugin": "^8.2.5",
|
"@cool-vue/vite-plugin": "^8.2.5",
|
||||||
"@dcloudio/types": "^3.4.16",
|
"@dcloudio/types": "^3.4.16",
|
||||||
"@types/node": "^24.0.15",
|
"@types/node": "^24.0.15",
|
||||||
|
|||||||
@@ -5,12 +5,13 @@
|
|||||||
<cl-button @tap="chooseImage">{{ t("选择图片") }}</cl-button>
|
<cl-button @tap="chooseImage">{{ t("选择图片") }}</cl-button>
|
||||||
|
|
||||||
<cl-list border :pt="{ className: 'mt-5' }">
|
<cl-list border :pt="{ className: 'mt-5' }">
|
||||||
<cl-list-item :label="t('调节裁剪框大小')">
|
<cl-list-item :label="t('可调节裁剪框大小')">
|
||||||
<cl-switch v-model="resizable"></cl-switch>
|
<cl-switch v-model="resizable"></cl-switch>
|
||||||
</cl-list-item>
|
</cl-list-item>
|
||||||
</cl-list>
|
</cl-list>
|
||||||
</demo-item>
|
</demo-item>
|
||||||
</view>
|
</view>
|
||||||
|
</cl-page>
|
||||||
|
|
||||||
<cl-cropper
|
<cl-cropper
|
||||||
ref="cropperRef"
|
ref="cropperRef"
|
||||||
@@ -18,7 +19,6 @@
|
|||||||
@crop="onCrop"
|
@crop="onCrop"
|
||||||
@load="onImageLoad"
|
@load="onImageLoad"
|
||||||
></cl-cropper>
|
></cl-cropper>
|
||||||
</cl-page>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@@ -43,11 +43,9 @@ function chooseImage() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCrop(result: any) {
|
function onCrop(url: string) {
|
||||||
console.log("裁剪结果:", result);
|
uni.previewImage({
|
||||||
uni.showToast({
|
urls: [url]
|
||||||
title: "裁剪完成",
|
|
||||||
icon: "success"
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,6 +54,6 @@ function onImageLoad(e: UniImageLoadEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onReady(() => {
|
onReady(() => {
|
||||||
cropperRef.value!.open('https://uni-docs.cool-js.com/demo/pages/demo/static/bg2.png');
|
cropperRef.value!.open("https://uni-docs.cool-js.com/demo/pages/demo/static/bg2.png");
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@@ -22,8 +22,8 @@ importers:
|
|||||||
specifier: ^7.27.6
|
specifier: ^7.27.6
|
||||||
version: 7.28.1
|
version: 7.28.1
|
||||||
'@cool-vue/ai':
|
'@cool-vue/ai':
|
||||||
specifier: ^1.1.4
|
specifier: ^1.1.5
|
||||||
version: 1.1.4
|
version: 1.1.5
|
||||||
'@cool-vue/vite-plugin':
|
'@cool-vue/vite-plugin':
|
||||||
specifier: ^8.2.5
|
specifier: ^8.2.5
|
||||||
version: 8.2.5
|
version: 8.2.5
|
||||||
@@ -81,8 +81,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==}
|
resolution: {integrity: sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@cool-vue/ai@1.1.4':
|
'@cool-vue/ai@1.1.5':
|
||||||
resolution: {integrity: sha512-1OKM1PnxMYzpzSTC7RjqnEcpwWKhAAns5/YJ5yi3RJY5vRRV6ZA0MbeMYvgNLLkSg5qEsUrC0lanKyX26B0R6g==}
|
resolution: {integrity: sha512-H3A9uml1uiux+g9UPcZT119W3WepvxTx5hs38chwnaj3/zBEF0J2pDI0HNq5FShoHZLQ6+Rq+R7Se0X+CmNU5Q==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
'@cool-vue/vite-plugin@8.2.5':
|
'@cool-vue/vite-plugin@8.2.5':
|
||||||
@@ -1358,7 +1358,7 @@ snapshots:
|
|||||||
'@babel/helper-string-parser': 7.27.1
|
'@babel/helper-string-parser': 7.27.1
|
||||||
'@babel/helper-validator-identifier': 7.27.1
|
'@babel/helper-validator-identifier': 7.27.1
|
||||||
|
|
||||||
'@cool-vue/ai@1.1.4':
|
'@cool-vue/ai@1.1.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
axios: 1.10.0
|
axios: 1.10.0
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
|
|||||||
4
types/uni-app.d.ts
vendored
4
types/uni-app.d.ts
vendored
@@ -394,8 +394,8 @@ declare interface UniElement {
|
|||||||
style: CSSStyleDeclaration;
|
style: CSSStyleDeclaration;
|
||||||
classList: string[];
|
classList: string[];
|
||||||
takeSnapshot(options: {
|
takeSnapshot(options: {
|
||||||
success: (res: { tempFilePath: string }) => void;
|
success?: (res: { tempFilePath: string }) => void;
|
||||||
fail: (err: { errCode: number; errMsg: string }) => void;
|
fail?: (err: { errCode: number; errMsg: string }) => void;
|
||||||
}): void;
|
}): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
<view
|
<view
|
||||||
class="cl-cropper"
|
class="cl-cropper"
|
||||||
:class="[pt.className]"
|
:class="[pt.className]"
|
||||||
@touchstart="onImageTouchStart"
|
@touchstart="onTouchStart"
|
||||||
@touchmove.stop.prevent="onImageTouchMove"
|
@touchmove.stop.prevent="onTouchMove"
|
||||||
@touchend="onImageTouchEnd"
|
@touchend="onTouchEnd"
|
||||||
@touchcancel="onImageTouchEnd"
|
@touchcancel="onTouchEnd"
|
||||||
v-if="visible"
|
v-if="visible"
|
||||||
>
|
>
|
||||||
<!-- 图片容器 - 可拖拽和缩放的图片区域 -->
|
<!-- 图片容器 - 可拖拽和缩放的图片区域 -->
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
:class="[pt.image?.className]"
|
:class="[pt.image?.className]"
|
||||||
:src="imageUrl"
|
:src="imageUrl"
|
||||||
:style="imageStyle"
|
:style="imageStyle"
|
||||||
@load="onImageLoaded as any"
|
@load="onImageLoaded"
|
||||||
></image>
|
></image>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -44,6 +44,29 @@
|
|||||||
<view class="cl-cropper__guide-line cl-cropper__guide-line--h2"></view>
|
<view class="cl-cropper__guide-line cl-cropper__guide-line--h2"></view>
|
||||||
<view class="cl-cropper__guide-line cl-cropper__guide-line--v1"></view>
|
<view class="cl-cropper__guide-line cl-cropper__guide-line--v1"></view>
|
||||||
<view class="cl-cropper__guide-line cl-cropper__guide-line--v2"></view>
|
<view class="cl-cropper__guide-line cl-cropper__guide-line--v2"></view>
|
||||||
|
|
||||||
|
<view class="cl-cropper__guide-text">
|
||||||
|
<cl-text
|
||||||
|
:pt="{
|
||||||
|
className: '!text-xl'
|
||||||
|
}"
|
||||||
|
color="white"
|
||||||
|
>
|
||||||
|
{{ cropBox.width }}
|
||||||
|
</cl-text>
|
||||||
|
|
||||||
|
<cl-icon name="close-line" color="white"></cl-icon>
|
||||||
|
|
||||||
|
<cl-text
|
||||||
|
:pt="{
|
||||||
|
className: '!text-xl'
|
||||||
|
}"
|
||||||
|
color="white"
|
||||||
|
>
|
||||||
|
{{ cropBox.height }}
|
||||||
|
</cl-text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<template v-if="resizable">
|
<template v-if="resizable">
|
||||||
@@ -52,13 +75,12 @@
|
|||||||
:key="item"
|
:key="item"
|
||||||
class="cl-cropper__drag-point"
|
class="cl-cropper__drag-point"
|
||||||
:class="[`cl-cropper__drag-point--${item}`]"
|
:class="[`cl-cropper__drag-point--${item}`]"
|
||||||
@touchstart="onResizeStart($event as TouchEvent, item)"
|
@touchstart.stop="onResizeStart($event as TouchEvent, item)"
|
||||||
>
|
>
|
||||||
<view class="cl-cropper__corner-indicator"></view>
|
<view class="cl-cropper__corner-indicator"></view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 底部按钮组 -->
|
<!-- 底部按钮组 -->
|
||||||
<view class="cl-cropper__actions" :class="[pt.actions?.className]">
|
<view class="cl-cropper__actions" :class="[pt.actions?.className]">
|
||||||
@@ -94,16 +116,28 @@
|
|||||||
|
|
||||||
<!-- 确定 -->
|
<!-- 确定 -->
|
||||||
<view class="cl-cropper__actions-item">
|
<view class="cl-cropper__actions-item">
|
||||||
<cl-icon name="check-line" color="white" :size="50" @tap="performCrop"></cl-icon>
|
<cl-icon name="check-line" color="white" :size="50" @tap="toPng"></cl-icon>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 裁剪用 -->
|
||||||
|
<view class="cl-cropper__canvas">
|
||||||
|
<canvas
|
||||||
|
ref="canvasRef"
|
||||||
|
:id="canvasId"
|
||||||
|
:style="{
|
||||||
|
height: `${cropBox.height}px`,
|
||||||
|
width: `${cropBox.width}px`
|
||||||
|
}"
|
||||||
|
></canvas>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, reactive, nextTick } from "vue";
|
import { computed, ref, reactive, nextTick, getCurrentInstance } from "vue";
|
||||||
import type { PassThroughProps } from "../../types";
|
import type { PassThroughProps } from "../../types";
|
||||||
import { parsePt, usePage } from "@/cool";
|
import { canvasToPng, parsePt, usePage, uuid } from "@/cool";
|
||||||
|
|
||||||
// 定义遮罩层样式类型
|
// 定义遮罩层样式类型
|
||||||
type MaskStyle = {
|
type MaskStyle = {
|
||||||
@@ -193,9 +227,18 @@ const props = defineProps({
|
|||||||
// 定义事件发射器
|
// 定义事件发射器
|
||||||
const emit = defineEmits(["crop", "load", "error"]);
|
const emit = defineEmits(["crop", "load", "error"]);
|
||||||
|
|
||||||
|
// 获取当前实例
|
||||||
|
const { proxy } = getCurrentInstance()!;
|
||||||
|
|
||||||
// 获取页面实例,用于获取视图尺寸
|
// 获取页面实例,用于获取视图尺寸
|
||||||
const page = usePage();
|
const page = usePage();
|
||||||
|
|
||||||
|
// 创建唯一的canvas ID
|
||||||
|
const canvasId = `cl-cropper__${uuid()}`;
|
||||||
|
|
||||||
|
// 创建canvas实例
|
||||||
|
const canvasRef = ref<UniElement | null>(null);
|
||||||
|
|
||||||
// 像素取整工具函数 - 避免小数点造成的样式兼容问题
|
// 像素取整工具函数 - 避免小数点造成的样式兼容问题
|
||||||
function toPixel(value: number): number {
|
function toPixel(value: number): number {
|
||||||
return Math.round(value); // 四舍五入取整
|
return Math.round(value); // 四舍五入取整
|
||||||
@@ -363,7 +406,7 @@ function getRotatedImageSize(): Size {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算双指缩放时的最小图片尺寸(简化版本,确保能覆盖裁剪框)
|
// 计算双指缩放时的最小图片尺寸
|
||||||
function getMinImageSizeForPinch(): Size {
|
function getMinImageSizeForPinch(): Size {
|
||||||
// 如果图片未加载,返回零尺寸
|
// 如果图片未加载,返回零尺寸
|
||||||
if (!imageInfo.isLoaded) {
|
if (!imageInfo.isLoaded) {
|
||||||
@@ -583,9 +626,6 @@ function onImageLoaded(e: UniImageLoadEvent) {
|
|||||||
|
|
||||||
// 开始调整裁剪框尺寸的函数
|
// 开始调整裁剪框尺寸的函数
|
||||||
function onResizeStart(e: TouchEvent, direction: string) {
|
function onResizeStart(e: TouchEvent, direction: string) {
|
||||||
// 阻止事件冒泡到图片容器
|
|
||||||
e.stopPropagation(); // 避免触发图片的触摸事件
|
|
||||||
|
|
||||||
// 设置调整状态
|
// 设置调整状态
|
||||||
touch.isTouching = true; // 标记正在触摸
|
touch.isTouching = true; // 标记正在触摸
|
||||||
touch.mode = "resizing"; // 设置为调整尺寸模式
|
touch.mode = "resizing"; // 设置为调整尺寸模式
|
||||||
@@ -803,7 +843,7 @@ function onResizeEnd() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 处理图片触摸开始事件的函数
|
// 处理图片触摸开始事件的函数
|
||||||
function onImageTouchStart(e: TouchEvent) {
|
function onTouchStart(e: TouchEvent) {
|
||||||
// 如果组件图片未加载,直接返回
|
// 如果组件图片未加载,直接返回
|
||||||
if (!imageInfo.isLoaded) return;
|
if (!imageInfo.isLoaded) return;
|
||||||
|
|
||||||
@@ -842,19 +882,14 @@ function onImageTouchStart(e: TouchEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 处理图片触摸移动事件的函数
|
// 处理图片触摸移动事件的函数
|
||||||
function onImageTouchMove(e: TouchEvent) {
|
function onTouchMove(e: TouchEvent) {
|
||||||
|
if (!touch.isTouching) return;
|
||||||
|
|
||||||
if (touch.mode == "resizing") {
|
if (touch.mode == "resizing") {
|
||||||
onResizeMove(e);
|
onResizeMove(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果组件不在触摸状态或不是图片操作模式,直接返回
|
|
||||||
if (!touch.isTouching || touch.mode != "image") return;
|
|
||||||
|
|
||||||
// 阻止默认行为和事件冒泡
|
|
||||||
e.preventDefault(); // 阻止页面滚动等默认行为
|
|
||||||
e.stopPropagation(); // 阻止事件向上冒泡
|
|
||||||
|
|
||||||
// 根据触摸点数量判断操作类型
|
// 根据触摸点数量判断操作类型
|
||||||
if (e.touches.length == 1) {
|
if (e.touches.length == 1) {
|
||||||
// 单指拖拽模式
|
// 单指拖拽模式
|
||||||
@@ -922,7 +957,7 @@ function onImageTouchMove(e: TouchEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 处理图片触摸结束事件的函数
|
// 处理图片触摸结束事件的函数
|
||||||
function onImageTouchEnd() {
|
function onTouchEnd() {
|
||||||
if (touch.mode == "resizing") {
|
if (touch.mode == "resizing") {
|
||||||
onResizeEnd();
|
onResizeEnd();
|
||||||
return;
|
return;
|
||||||
@@ -958,6 +993,40 @@ function resetCropper() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 是否显示
|
||||||
|
const visible = ref(false);
|
||||||
|
|
||||||
|
// 图片地址
|
||||||
|
const imageUrl = ref("");
|
||||||
|
|
||||||
|
// 打开裁剪器
|
||||||
|
function open(url: string) {
|
||||||
|
visible.value = true;
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
imageUrl.value = url;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭裁剪器
|
||||||
|
function close() {
|
||||||
|
visible.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新选择图片
|
||||||
|
function chooseImage() {
|
||||||
|
uni.chooseImage({
|
||||||
|
count: 1,
|
||||||
|
sizeType: ["original", "compressed"],
|
||||||
|
sourceType: ["album", "camera"],
|
||||||
|
success: (res) => {
|
||||||
|
if (res.tempFilePaths.length > 0) {
|
||||||
|
open(res.tempFilePaths[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 切换水平翻转状态的函数
|
// 切换水平翻转状态的函数
|
||||||
function toggleHorizontalFlip() {
|
function toggleHorizontalFlip() {
|
||||||
flipHorizontal.value = !flipHorizontal.value; // 切换水平翻转状态
|
flipHorizontal.value = !flipHorizontal.value; // 切换水平翻转状态
|
||||||
@@ -994,53 +1063,76 @@ function rotate90() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行裁剪操作的函数
|
// 执行裁剪转图片
|
||||||
function performCrop() {
|
async function toPng(): Promise<string> {
|
||||||
// 检查图片是否已加载
|
return new Promise((resolve) => {
|
||||||
if (!imageInfo.isLoaded) {
|
uni.createCanvasContextAsync({
|
||||||
emit("error", "图片尚未加载完成,无法执行裁剪操作"); // 发送错误事件
|
id: canvasId,
|
||||||
return; // 提前退出
|
component: proxy,
|
||||||
|
success: (context: CanvasContext) => {
|
||||||
|
// 获取绘图上下文
|
||||||
|
const ctx = context.getContext("2d")!;
|
||||||
|
|
||||||
|
// #ifdef APP
|
||||||
|
ctx!.reset();
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifndef APP
|
||||||
|
ctx!.clearRect(0, 0, cropBox.width, cropBox.height);
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// 获取设备像素比
|
||||||
|
const dpr = uni.getDeviceInfo().devicePixelRatio ?? 1;
|
||||||
|
|
||||||
|
// #ifndef H5
|
||||||
|
// 设置缩放比例
|
||||||
|
ctx!.scale(dpr, dpr);
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// 设置宽高
|
||||||
|
ctx!.canvas.width = cropBox.width;
|
||||||
|
ctx!.canvas.height = cropBox.height;
|
||||||
|
|
||||||
|
let img: Image;
|
||||||
|
|
||||||
|
// 微信小程序环境创建图片
|
||||||
|
// #ifdef MP-WEIXIN || APP-HARMONY
|
||||||
|
img = context.createImage();
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// 其他环境创建图片
|
||||||
|
// #ifndef MP-WEIXIN || APP-HARMONY
|
||||||
|
img = new Image(cropBox.width, cropBox.height);
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// 设置图片源并在加载完成后绘制
|
||||||
|
img.src = imageUrl.value;
|
||||||
|
img.onload = () => {
|
||||||
|
ctx!.drawImage(img, cropBox.x, cropBox.y, cropBox.width, cropBox.height);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
canvasToPng({
|
||||||
|
proxy,
|
||||||
|
canvasId,
|
||||||
|
canvasRef: canvasRef.value!
|
||||||
|
})
|
||||||
|
.then((url) => {
|
||||||
|
emit("crop", url);
|
||||||
|
resolve(url);
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
}, 10);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 是否显示
|
|
||||||
const visible = ref(false);
|
|
||||||
|
|
||||||
// 图片地址
|
|
||||||
const imageUrl = ref("");
|
|
||||||
|
|
||||||
// 打开裁剪器
|
|
||||||
function open(url: string) {
|
|
||||||
visible.value = true;
|
|
||||||
|
|
||||||
nextTick(() => {
|
|
||||||
imageUrl.value = url;
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// 关闭裁剪器
|
|
||||||
function close() {
|
|
||||||
visible.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重新选择图片
|
|
||||||
function chooseImage() {
|
|
||||||
uni.chooseImage({
|
|
||||||
count: 1,
|
|
||||||
sizeType: ["original", "compressed"],
|
|
||||||
sourceType: ["album", "camera"],
|
|
||||||
success: (res) => {
|
|
||||||
if (res.tempFilePaths.length > 0) {
|
|
||||||
open(res.tempFilePaths[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
open,
|
open,
|
||||||
close,
|
close,
|
||||||
chooseImage
|
chooseImage,
|
||||||
|
toPng
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -1050,7 +1142,7 @@ defineExpose({
|
|||||||
z-index: 510;
|
z-index: 510;
|
||||||
|
|
||||||
&__image {
|
&__image {
|
||||||
@apply absolute top-0 left-0 flex items-center justify-center w-full h-full;
|
@apply absolute top-0 left-0 flex items-center justify-center w-full h-full pointer-events-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__mask {
|
&__mask {
|
||||||
@@ -1068,7 +1160,7 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__crop-area {
|
&__crop-area {
|
||||||
@apply relative w-full h-full overflow-visible duration-200;
|
@apply relative w-full h-full overflow-visible duration-200 pointer-events-none;
|
||||||
@apply border border-solid;
|
@apply border border-solid;
|
||||||
border-color: rgba(255, 255, 255, 0.5);
|
border-color: rgba(255, 255, 255, 0.5);
|
||||||
|
|
||||||
@@ -1078,6 +1170,7 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__guide-lines {
|
&__guide-lines {
|
||||||
|
@apply flex justify-center items-center;
|
||||||
@apply absolute top-0 left-0 w-full h-full pointer-events-none opacity-0 duration-200;
|
@apply absolute top-0 left-0 w-full h-full pointer-events-none opacity-0 duration-200;
|
||||||
|
|
||||||
&.is-show {
|
&.is-show {
|
||||||
@@ -1109,59 +1202,63 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__guide-text {
|
||||||
|
@apply absolute flex flex-row items-center justify-center;
|
||||||
|
}
|
||||||
|
|
||||||
&__corner-indicator {
|
&__corner-indicator {
|
||||||
@apply border-white border-solid border-b-transparent border-l-transparent absolute duration-200 pointer-events-auto;
|
@apply border-white border-solid border-b-transparent border-l-transparent absolute duration-200;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__drag-point {
|
&__drag-point {
|
||||||
@apply absolute duration-200 flex items-center justify-center pointer-events-auto;
|
@apply absolute duration-200 flex items-center justify-center overflow-visible;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
|
||||||
&--tl {
|
&--tl {
|
||||||
top: -20px;
|
top: 0;
|
||||||
left: -20px;
|
left: 0;
|
||||||
|
|
||||||
.cl-cropper__corner-indicator {
|
.cl-cropper__corner-indicator {
|
||||||
transform: rotate(-90deg);
|
transform: rotate(-90deg);
|
||||||
left: 20px;
|
left: -1px;
|
||||||
top: 20px;
|
top: -1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&--tr {
|
&--tr {
|
||||||
top: -20px;
|
top: 0;
|
||||||
right: -20px;
|
right: 0;
|
||||||
|
|
||||||
.cl-cropper__corner-indicator {
|
.cl-cropper__corner-indicator {
|
||||||
transform: rotate(0deg);
|
transform: rotate(0deg);
|
||||||
right: 20px;
|
right: -1px;
|
||||||
top: 20px;
|
top: -1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&--bl {
|
&--bl {
|
||||||
bottom: -20px;
|
bottom: 0;
|
||||||
left: -20px;
|
left: 0;
|
||||||
|
|
||||||
.cl-cropper__corner-indicator {
|
.cl-cropper__corner-indicator {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
bottom: 20px;
|
bottom: -1px;
|
||||||
left: 20px;
|
left: -1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&--br {
|
&--br {
|
||||||
bottom: -20px;
|
bottom: 0;
|
||||||
right: -20px;
|
right: 0;
|
||||||
|
|
||||||
.cl-cropper__corner-indicator {
|
.cl-cropper__corner-indicator {
|
||||||
transform: rotate(90deg);
|
transform: rotate(90deg);
|
||||||
bottom: 20px;
|
bottom: -1px;
|
||||||
right: 20px;
|
right: 0-1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1176,5 +1273,10 @@ defineExpose({
|
|||||||
@apply flex flex-row justify-center items-center flex-1;
|
@apply flex flex-row justify-center items-center flex-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__canvas {
|
||||||
|
@apply absolute top-0;
|
||||||
|
left: -10000px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ defineOptions({
|
|||||||
name: "cl-sign"
|
name: "cl-sign"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 定义组件属性
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
pt: {
|
pt: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -75,8 +76,10 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 定义事件发射器
|
||||||
const emit = defineEmits(["change"]);
|
const emit = defineEmits(["change"]);
|
||||||
|
|
||||||
|
// 获取当前实例
|
||||||
const { proxy } = getCurrentInstance()!;
|
const { proxy } = getCurrentInstance()!;
|
||||||
|
|
||||||
// 触摸点类型
|
// 触摸点类型
|
||||||
|
|||||||
1
uni_modules/cool-ui/types/component.d.ts
vendored
1
uni_modules/cool-ui/types/component.d.ts
vendored
@@ -157,4 +157,5 @@ declare type ClCropperComponentPublicInstance = {
|
|||||||
open: (url: string) => void;
|
open: (url: string) => void;
|
||||||
close: () => void;
|
close: () => void;
|
||||||
chooseImage: () => void;
|
chooseImage: () => void;
|
||||||
|
toPng: () => Promise<string>;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user