兼容 ios

This commit is contained in:
icssoa
2025-09-04 20:18:18 +08:00
parent 083c8b1325
commit f01d1107b9
15 changed files with 316 additions and 146 deletions

1
.gitignore vendored
View File

@@ -9,6 +9,7 @@ npm-debug.log*
# Editor directories and files # Editor directories and files
.project .project
.idea .idea
.hbuilderx
*.suo *.suo
*.ntvs* *.ntvs*
*.njsproj *.njsproj

View File

@@ -6,18 +6,18 @@
</demo-item> </demo-item>
<demo-item :label="t('不同类型')"> <demo-item :label="t('不同类型')">
<view class="flex flex-row flex-wrap mb-2"> <view class="flex flex-row flex-wrap mb-2 overflow-visible">
<cl-button type="primary">{{ t("主要") }}</cl-button> <cl-button type="primary">{{ t("主要") }}</cl-button>
<cl-button type="success">{{ t("成功") }}</cl-button> <cl-button type="success">{{ t("成功") }}</cl-button>
<cl-button type="warn">{{ t("警告") }}</cl-button> <cl-button type="warn">{{ t("警告") }}</cl-button>
</view> </view>
<view class="flex flex-row mb-2"> <view class="flex flex-row mb-2 overflow-visible">
<cl-button type="error">{{ t("危险") }}</cl-button> <cl-button type="error">{{ t("危险") }}</cl-button>
<cl-button type="info">{{ t("信息") }}</cl-button> <cl-button type="info">{{ t("信息") }}</cl-button>
</view> </view>
<view class="flex flex-row"> <view class="flex flex-row overflow-visible">
<cl-button type="light">{{ t("浅色") }}</cl-button> <cl-button type="light">{{ t("浅色") }}</cl-button>
<cl-button type="dark">{{ t("深色") }}</cl-button> <cl-button type="dark">{{ t("深色") }}</cl-button>
</view> </view>

View File

@@ -1,6 +1,12 @@
<template> <template>
<cl-page> <cl-page>
<view class="p-3 overflow-visible"> <view class="p-3">
<demo-item>
<cl-text color="info">
{{ t("长按项即可拖动排序") }}
</cl-text>
</demo-item>
<demo-item :label="t('单列排序')"> <demo-item :label="t('单列排序')">
<cl-draggable v-model="list"> <cl-draggable v-model="list">
<template #item="{ item, index }"> <template #item="{ item, index }">
@@ -16,6 +22,18 @@
</cl-draggable> </cl-draggable>
</demo-item> </demo-item>
<demo-item :label="t('不需要长按')">
<cl-draggable v-model="list5" :long-press="false">
<template #item="{ item }">
<view
class="flex flex-row items-center p-3 bg-surface-100 rounded-lg mb-2 dark:!bg-surface-700"
>
<cl-text>{{ (item as UTSJSONObject).label }}</cl-text>
</view>
</template>
</cl-draggable>
</demo-item>
<demo-item :label="t('结合列表使用')"> <demo-item :label="t('结合列表使用')">
<cl-list border> <cl-list border>
<cl-draggable v-model="list2"> <cl-draggable v-model="list2">
@@ -26,8 +44,12 @@
arrow arrow
:pt="{ :pt="{
inner: { inner: {
className: className: parseClass([
dragging && dragIndex == index ? '!bg-surface-100' : '' [
dragging && dragIndex == index,
isDark ? '!bg-surface-700' : '!bg-surface-100'
]
])
} }
}" }"
></cl-list-item> ></cl-list-item>
@@ -75,41 +97,57 @@
import { t } from "@/locale"; import { t } from "@/locale";
import DemoItem from "../components/item.uvue"; import DemoItem from "../components/item.uvue";
import { ref } from "vue"; import { ref } from "vue";
import { isDark, parseClass } from "@/cool";
// list李白《将进酒》
const list = ref<UTSJSONObject[]>([ const list = ref<UTSJSONObject[]>([
{ {
label: "明月几时有,把酒问青天" label: "君不见黄河之水天上来"
}, },
{ {
label: "不知天上宫阙,今夕是何年", label: "奔流到海不复回",
disabled: true disabled: true
}, },
{ {
label: "我欲乘风归去,又恐琼楼玉宇" label: "君不见高堂明镜悲白发"
}, },
{ {
label: "高处不胜寒,起舞弄清影" label: "朝如青丝暮成雪"
}, },
{ {
label: "何似在人间" label: "人生得意须尽欢"
} }
]); ]);
// list5杜甫《春望》
const list5 = ref<UTSJSONObject[]>([
{
label: "国破山河在"
},
{
label: "城春草木深"
},
{
label: "感时花溅泪"
}
]);
// list2王之涣《登鹳雀楼》
const list2 = ref<UTSJSONObject[]>([ const list2 = ref<UTSJSONObject[]>([
{ {
label: "明月几时有,把酒问青天" label: "白日依山尽"
}, },
{ {
label: "不知天上宫阙,今夕是何年" label: "黄河入海流"
}, },
{ {
label: "我欲乘风归去,又恐琼楼玉宇" label: "欲穷千里目"
}, },
{ {
label: "高处不胜寒,起舞弄清影" label: "更上一层楼"
}, },
{ {
label: "何似在人间" label: "一览众山小"
} }
]); ]);

View File

@@ -19,7 +19,11 @@
<template #bottom> <template #bottom>
<view class="py-3"> <view class="py-3">
<cl-loadmore :loading="loading" v-if="list.length > 0"></cl-loadmore> <cl-loadmore
v-if="list.length > 0"
:loading="loading"
safe-area-bottom
></cl-loadmore>
</view> </view>
</template> </template>
</cl-list-view> </cl-list-view>

View File

@@ -36,7 +36,7 @@
</template> </template>
</cl-waterfall> </cl-waterfall>
<cl-loadmore :loading="true"></cl-loadmore> <cl-loadmore :loading="true" safe-area-bottom></cl-loadmore>
</view> </view>
</cl-page> </cl-page>
</template> </template>

20
types/uni-app.d.ts vendored
View File

@@ -446,6 +446,26 @@ declare interface UniElement {
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;
getDrawableContext(): DrawableContext;
animate(
keyframes: UniAnimationKeyframe | UniAnimationKeyframe[],
options?:
| {
delay?: number;
direction?: "normal" | "reverse" | "alternate" | "alternate-reverse";
duration?: number;
easing?:
| "ease"
| "ease-in"
| "ease-out"
| "ease-in-out"
| "linear"
| "cubic-bezier";
fill?: "backwards" | "forwards" | "both" | "none";
iterations?: number;
}
| number
): { id: string; playState: "running" | "paused" | "finished" | "idle" } | null;
} }
declare interface CanvasContext extends HTMLCanvasElement { declare interface CanvasContext extends HTMLCanvasElement {

View File

@@ -0,0 +1,5 @@
{
"dependencies": {
"@ohos/svg": "2.2.1"
}
}

View File

@@ -0,0 +1,5 @@
import { BuilderNode } from "@kit.ArkUI";
export class CoolSvg {
load(src: string, color: string) {}
}

View File

@@ -10,6 +10,7 @@
> >
<!-- 图片容器 - 可拖拽和缩放的图片区域 --> <!-- 图片容器 - 可拖拽和缩放的图片区域 -->
<view class="cl-cropper__image"> <view class="cl-cropper__image">
<!-- @vue-ignore -->
<image <image
class="cl-cropper__image-inner" class="cl-cropper__image-inner"
:class="[ :class="[

View File

@@ -3,28 +3,35 @@
class="cl-draggable" class="cl-draggable"
:class="[ :class="[
{ {
'cl-draggable--grid': props.columns > 1 'cl-draggable--columns': props.columns > 1
}, },
pt.className pt.className
]" ]"
> >
<!-- @vue-ignore -->
<view <view
v-for="(item, index) in list" v-for="(item, index) in list"
:key="getItemKey(item, index)" :key="getItemKey(item, index)"
class="cl-draggable__item" class="cl-draggable__item"
:class="[ :class="[
{ {
'cl-draggable__item--disabled': disabled 'cl-draggable__item--disabled': disabled,
}, 'cl-draggable__item--dragging': dragging && dragIndex == index,
dragging && dragIndex == index ? `opacity-80 ${pt.ghost?.className}` : '' 'cl-draggable__item--animating': dragging && dragIndex != index
}
]" ]"
:style="getItemStyle(index)" :style="getItemStyle(index)"
@touchstart=" @touchstart="
(event: UniTouchEvent) => { (event: UniTouchEvent) => {
onTouchStart(event, index); onTouchStart(event, index, 'touch');
} }
" "
@touchmove.stop.prevent="onTouchMove" @longpress="
(event: UniTouchEvent) => {
onTouchStart(event, index, 'longpress');
}
"
@touchmove="onTouchMove"
@touchend="onTouchEnd" @touchend="onTouchEnd"
> >
<slot <slot
@@ -44,6 +51,7 @@
import { computed, ref, getCurrentInstance, type PropType, watch } from "vue"; import { computed, ref, getCurrentInstance, type PropType, watch } from "vue";
import { isNull, parsePt, uuid } from "@/cool"; import { isNull, parsePt, uuid } from "@/cool";
import type { PassThroughProps } from "../../types"; import type { PassThroughProps } from "../../types";
import { vibrate } from "@/uni_modules/cool-vibrate";
defineOptions({ defineOptions({
name: "cl-draggable" name: "cl-draggable"
@@ -89,15 +97,15 @@ const props = defineProps({
type: Boolean, type: Boolean,
default: false default: false
}, },
/** 动画持续时间(毫秒) */
animation: {
type: Number,
default: 150
},
/** 列数1为单列纵向布局>1为多列网格布局 */ /** 列数1为单列纵向布局>1为多列网格布局 */
columns: { columns: {
type: Number, type: Number,
default: 1 default: 1
},
// 是否需要长按触发
longPress: {
type: Boolean,
default: true
} }
}); });
@@ -376,12 +384,6 @@ function getItemStyle(index: number) {
return style; return style;
} }
// 为非拖拽元素添加过渡动画
if (props.animation > 0 && !isCurrent) {
style["transition-property"] = "transform";
style["transition-duration"] = `${props.animation}ms`;
}
// 拖拽状态下的样式处理 // 拖拽状态下的样式处理
if (dragging.value) { if (dragging.value) {
if (isCurrent) { if (isCurrent) {
@@ -391,11 +393,9 @@ function getItemStyle(index: number) {
} else { } else {
// 其他元素:显示排序预览位移 // 其他元素:显示排序预览位移
const translateOffset = getItemTranslateOffset(index); const translateOffset = getItemTranslateOffset(index);
if (translateOffset.x != 0 || translateOffset.y != 0) {
style["transform"] = `translate(${translateOffset.x}px, ${translateOffset.y}px)`; style["transform"] = `translate(${translateOffset.x}px, ${translateOffset.y}px)`;
} }
} }
}
return style; return style;
} }
@@ -513,22 +513,31 @@ function checkMovedToOtherElement(): boolean {
* @param event 触摸事件对象 * @param event 触摸事件对象
* @param index 触摸的项目索引 * @param index 触摸的项目索引
*/ */
async function onTouchStart(event: UniTouchEvent, index: number): Promise<void> { async function onTouchStart(event: UniTouchEvent, index: number, type: string) {
// 如果是长按触发,但未开启长按功能,则直接返回
if (type == "longpress" && !props.longPress) return;
// 如果是普通触摸触发,但已开启长按功能,则直接返回
if (type == "touch" && props.longPress) return;
// 检查是否禁用或索引无效 // 检查是否禁用或索引无效
if (props.disabled) return; if (props.disabled) return;
if (getItemDisabled(index)) return; if (getItemDisabled(index)) return;
if (index < 0 || index >= list.value.length) return; if (index < 0 || index >= list.value.length) return;
// 获取触摸点
const touch = event.touches[0]; const touch = event.touches[0];
// 初始化拖拽状态 // 初始化拖拽状态
dragging.value = true; dragging.value = true;
// 初始化拖拽索引
dragIndex.value = index; dragIndex.value = index;
insertIndex.value = index; // 初始插入位置为原位置 insertIndex.value = index; // 初始插入位置为原位置
startX.value = touch.clientX; startX.value = touch.clientX;
startY.value = touch.clientY; startY.value = touch.clientY;
offsetX.value = 0; offsetX.value = 0;
offsetY.value = 0; offsetY.value = 0;
// 初始化拖拽数据项
dragItem.value = list.value[index]; dragItem.value = list.value[index];
// 先获取所有项目的位置信息,为后续计算做准备 // 先获取所有项目的位置信息,为后续计算做准备
@@ -536,6 +545,14 @@ async function onTouchStart(event: UniTouchEvent, index: number): Promise<void>
// 触发开始事件 // 触发开始事件
emit("start", index); emit("start", index);
// 震动
vibrate(1);
// 阻止事件冒泡
event.stopPropagation();
// 阻止默认行为
event.preventDefault();
} }
/** /**
@@ -575,7 +592,7 @@ function onTouchMove(event: TouchEvent): void {
} }
} }
// 阻止默认行为和事件冒泡 // 阻止默认行为
event.preventDefault(); event.preventDefault();
} }
@@ -585,7 +602,10 @@ function onTouchMove(event: TouchEvent): void {
function onTouchEnd(): void { function onTouchEnd(): void {
if (!dragging.value) return; if (!dragging.value) return;
// 旧索引
const oldIndex = dragIndex.value; const oldIndex = dragIndex.value;
// 新索引
const newIndex = insertIndex.value; const newIndex = insertIndex.value;
// 如果位置发生变化,立即更新数组 // 如果位置发生变化,立即更新数组
@@ -604,15 +624,11 @@ function onTouchEnd(): void {
dropping.value = true; dropping.value = true;
dragging.value = false; dragging.value = false;
// 让拖拽元素回到自然位置(偏移归零) // 重置所有状态
offsetX.value = 0; reset();
offsetY.value = 0;
// 等待放下动画完成后重置所有状态 // 等待放下动画完成后重置所有状态
setTimeout(() => {
emit("end", newIndex >= 0 ? newIndex : oldIndex); emit("end", newIndex >= 0 ? newIndex : oldIndex);
reset();
}, 10);
} }
/** /**
@@ -652,21 +668,30 @@ watch(
<style lang="scss" scoped> <style lang="scss" scoped>
.cl-draggable { .cl-draggable {
@apply flex-col relative overflow-visible; @apply flex-col relative overflow-visible;
}
.cl-draggable--grid { &--columns {
@apply flex-row flex-wrap; @apply flex-row flex-wrap;
} }
.cl-draggable__item { &__item {
@apply relative; @apply relative z-10;
}
.cl-draggable__item--dragging { // #ifdef APP-IOS
@apply opacity-80; @apply transition-none opacity-100;
} // #endif
.cl-draggable__item--disabled { &--dragging {
@apply opacity-80 z-20;
}
&--disabled {
@apply opacity-60; @apply opacity-60;
}
&--animating {
@apply duration-200;
transition-property: transform;
}
}
} }
</style> </style>

View File

@@ -22,8 +22,6 @@
:hold-keyboard="false" :hold-keyboard="false"
:clearable="false" :clearable="false"
@change="onChange" @change="onChange"
@focus="animateCursor(true)"
@blur="animateCursor(true)"
></cl-input> ></cl-input>
</view> </view>
@@ -36,12 +34,13 @@
{ {
'is-disabled': disabled, 'is-disabled': disabled,
'is-dark': isDark, 'is-dark': isDark,
'is-active': value.length == index && isFocus 'is-active': value.length >= index && isFocus
}, },
pt.item?.className pt.item?.className
]" ]"
> >
<cl-text <cl-text
:color="value.length >= index && isFocus ? 'primary' : ''"
:pt="{ :pt="{
className: pt.value?.className className: pt.value?.className
}" }"
@@ -50,9 +49,6 @@
<view <view
class="cl-input-otp__cursor" class="cl-input-otp__cursor"
:class="[pt.cursor?.className]" :class="[pt.cursor?.className]"
:style="{
opacity: cursorOpacity
}"
v-if="value.length == index && isFocus && item == ''" v-if="value.length == index && isFocus && item == ''"
></view> ></view>
</view> </view>
@@ -184,51 +180,6 @@ function onChange(val: string) {
emit("done", val); emit("done", val);
} }
} }
/**
* 光标闪烁透明度值
* 范围: 0.3-1.0
*/
const cursorOpacity = ref(0.3);
/**
* 光标闪烁动画帧ID
*/
let cursorAnimationId = 0;
/**
* 控制光标闪烁动画
* @param isIncreasing 透明度是否递增
*/
function animateCursor(isIncreasing: boolean) {
// #ifdef APP
// 未获得焦点时不执行动画
if (!isFocus.value) {
return;
}
// 取消上一次动画
if (cursorAnimationId != 0) {
cancelAnimationFrame(cursorAnimationId);
cursorAnimationId = 0;
}
// 执行动画帧
cursorAnimationId = requestAnimationFrame(() => {
// 根据方向调整透明度值
cursorOpacity.value += isIncreasing ? 0.01 : -0.01;
// 到达边界值时改变方向
if (cursorOpacity.value > 1) {
animateCursor(false);
} else if (cursorOpacity.value <= 0.3) {
animateCursor(true);
} else {
animateCursor(isIncreasing);
}
});
// #endif
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -248,7 +199,7 @@ function animateCursor(isIncreasing: boolean) {
} }
&__item { &__item {
@apply flex flex-row items-center justify-center; @apply flex flex-row items-center justify-center duration-100;
@apply border border-solid border-surface-200 rounded-lg bg-white; @apply border border-solid border-surface-200 rounded-lg bg-white;
height: 80rpx; height: 80rpx;
width: 80rpx; width: 80rpx;
@@ -272,10 +223,10 @@ function animateCursor(isIncreasing: boolean) {
} }
&__cursor { &__cursor {
@apply absolute; @apply absolute duration-100;
@apply bg-primary-500; @apply bg-primary-500;
width: 2rpx; width: 2rpx;
height: 36rpx; height: 24rpx;
} }
// #ifdef H5 || MP // #ifdef H5 || MP
@@ -285,7 +236,7 @@ function animateCursor(isIncreasing: boolean) {
@keyframes flash { @keyframes flash {
0% { 0% {
opacity: 0.3; opacity: 0;
} }
50% { 50% {
@@ -293,7 +244,7 @@ function animateCursor(isIncreasing: boolean) {
} }
100% { 100% {
opacity: 0.3; opacity: 0;
} }
} }
// #endif // #endif

View File

@@ -1,33 +1,25 @@
<template> <template>
<view <view
ref="loadingRef"
class="cl-loading" class="cl-loading"
:class="[ :class="[
{ {
'cl-loading--dark': isDark && color == '', 'cl-loading--dark': isDark && color == '',
'cl-loading--spin': loading, 'cl-loading--spin': loading,
'!border-primary-500': color == 'primary',
'!border-green-500': color == 'success',
'!border-yellow-500': color == 'warn',
'!border-red-500': color == 'error',
'!border-surface-500': color == 'info',
'!border-surface-700': color == 'dark',
'!border-white': color == 'light',
'!border-surface-300': color == 'disabled',
'!border-r-transparent': true '!border-r-transparent': true
}, },
pt.className pt.className
]" ]"
:style="{ :style="{
// #ifdef APP height: getPx(size!),
transform: `rotate(${rotate}deg)`, width: getPx(size!),
// #endif // #ifndef APP
height: getRpx(size!), borderWidth: '1px',
width: getRpx(size!),
borderWidth: getRpx(2),
borderTopColor: color, borderTopColor: color,
borderRightColor: 'transparent', borderRightColor: 'transparent',
borderBottomColor: color, borderBottomColor: color,
borderLeftColor: color borderLeftColor: color
// #endif
}" }"
v-if="loading" v-if="loading"
> >
@@ -35,8 +27,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted, ref, watch } from "vue"; import { computed, nextTick, onMounted, ref, shallowRef, watch } from "vue";
import { isDark, parsePt } from "@/cool"; import { ctx, isDark, parsePt } from "@/cool";
import type { ClIconProps } from "../cl-icon/props"; import type { ClIconProps } from "../cl-icon/props";
import { useSize } from "../../hooks"; import { useSize } from "../../hooks";
@@ -68,7 +60,7 @@ const props = defineProps({
} }
}); });
const { getRpx } = useSize(); const { getPxValue, getPx } = useSize();
// 透传样式类型定义 // 透传样式类型定义
type PassThrough = { type PassThrough = {
@@ -79,25 +71,113 @@ type PassThrough = {
// 解析透传样式 // 解析透传样式
const pt = computed(() => parsePt<PassThrough>(props.pt)); const pt = computed(() => parsePt<PassThrough>(props.pt));
// 旋转角度 // 组件引用
const rotate = ref(0); const loadingRef = shallowRef<UniElement | null>(null);
const color = computed<string>(() => {
if (props.color == "") {
return isDark.value ? "#ffffff" : (ctx.color["surface-700"] as string);
}
switch (props.color) {
case "primary":
return ctx.color["primary-500"] as string;
case "success":
return "#22c55e";
case "warn":
return "#eab308";
case "error":
return "#ef4444";
case "info":
return "#71717a";
case "dark":
return "#3f3f46";
case "light":
return "#ffffff";
case "disabled":
return "#d4d4d8";
default:
return props.color;
}
});
async function drawLoading() {
// #ifdef APP
await nextTick();
if (loadingRef.value == null) {
return;
}
const drawContext = loadingRef.value!.getDrawableContext();
// 重置画布准备绘制新的loading图形
drawContext!.reset();
drawContext!.beginPath();
// 获取loading图标的尺寸和半径
const size = getPxValue(props.size!);
const radius = size / 2;
const centerX = radius;
const centerY = radius;
// 设置线宽
const lineWidth = 1;
// 缺口角度为60度Math.PI / 3用于形成loading的缺口效果
const gapAngle = Math.PI / 3; // 缺口60度
// 起始角度为顶部(-90度
const startAngle = -Math.PI / 2; // 从顶部开始
// 结束角度为起始角度加上300度360-60形成环形缺口
const endAngle = startAngle + (2 * Math.PI - gapAngle); // 画300度
// 绘制圆弧形成loading环
drawContext!.arc(centerX, centerY, radius - lineWidth, startAngle, endAngle, false);
// 设置描边颜色和线宽
drawContext!.strokeStyle = color.value;
drawContext!.lineWidth = lineWidth;
// 执行描边操作
drawContext!.stroke();
// 更新画布显示
drawContext!.update();
// #endif
}
// 开始旋转动画 // 开始旋转动画
function start() { async function start() {
requestAnimationFrame(() => { // #ifdef APP
// 增加旋转角度 await drawLoading();
rotate.value += 1;
// 如果仍在加载中则继续旋转 if (loadingRef.value == null) {
if (props.loading) { return;
start();
} }
});
loadingRef.value!.animate(
[
{
transform: "rotate(0deg)"
},
{
transform: "rotate(360deg)"
}
],
{
duration: 2500,
easing: "linear",
iterations: 999999
}
);
// #endif
} }
// 组件挂载后监听loading状态 // 组件挂载后监听loading状态
onMounted(() => { onMounted(() => {
// #ifdef APP-UVUE // #ifdef APP
watch( watch(
computed(() => props.loading), computed(() => props.loading),
(val: boolean) => { (val: boolean) => {
@@ -110,6 +190,13 @@ onMounted(() => {
immediate: true immediate: true
} }
); );
watch(
computed(() => [props.color, props.size, isDark.value]),
() => {
drawLoading();
}
);
// #endif // #endif
}); });
</script> </script>
@@ -117,7 +204,10 @@ onMounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.cl-loading { .cl-loading {
@apply flex flex-row items-center justify-center rounded-full; @apply flex flex-row items-center justify-center rounded-full;
// #ifndef APP
@apply border-surface-700 border-solid; @apply border-surface-700 border-solid;
// #endif
&--dark { &--dark {
border-color: white !important; border-color: white !important;

View File

@@ -2,7 +2,7 @@
<view class="cl-loadmore-wrapper"> <view class="cl-loadmore-wrapper">
<view class="cl-loadmore"> <view class="cl-loadmore">
<cl-loading <cl-loading
:size="30" :size="28"
:pt="{ :pt="{
className: `mr-2 ${pt.icon?.className}` className: `mr-2 ${pt.icon?.className}`
}" }"
@@ -59,7 +59,7 @@ const props = defineProps({
// 是否显示底部安全区 // 是否显示底部安全区
safeAreaBottom: { safeAreaBottom: {
type: Boolean, type: Boolean,
default: true default: false
} }
}); });

View File

@@ -384,7 +384,7 @@ function onTouchEnd() {
angle: currentAngle.value angle: currentAngle.value
}); });
} }
vibrate(2); // 震动反馈 vibrate(1); // 震动反馈
} }
// 监听模式变化,重新初始化 // 监听模式变化,重新初始化

View File

@@ -1,5 +1,6 @@
import { computed, type ComputedRef } from "vue"; import { computed, type ComputedRef } from "vue";
import { config } from "../config"; import { config } from "../config";
import { rpx2px } from "@/cool";
/** /**
* 字号管理类 * 字号管理类
@@ -73,6 +74,35 @@ class Size {
} }
}; };
/**
* 获取px值
* @param val - 需要转换的值 10、10rpx、10px
* @returns 转换后的px值
*/
getPxValue = (val: number | string) => {
const scale = this.getScale();
if (typeof val == "string") {
const num = parseFloat(val);
const unit = val.replace(`${num}`, "");
if (unit == "px") {
return num * scale;
} else {
return rpx2px(num * scale);
}
} else {
return rpx2px(val * scale);
}
};
/**
* 获取px值
*/
getPx = (val: number | string) => {
return this.getPxValue(val) + "px";
};
/** /**
* 获取当前字号在预设中的索引 * 获取当前字号在预设中的索引
*/ */