| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- <template>
- <view
- ref="loadingRef"
- class="cl-loading"
- :class="[
- {
- 'cl-loading--dark': isDark && color == '',
- '!border-r-transparent': true
- },
- pt.className
- ]"
- :style="{
- height: getPx(size!),
- width: getPx(size!),
- borderWidth: '1px',
- borderTopColor: color,
- borderRightColor: 'transparent',
- borderBottomColor: color,
- borderLeftColor: color
- }"
- v-if="loading"
- >
- </view>
- </template>
- <script setup lang="ts">
- import { computed, onMounted, shallowRef, watch } from "vue";
- import { createAnimation, ctx, isDark, parsePt } from "@/cool";
- import type { ClIconProps } from "../cl-icon/props";
- import { useSize } from "../../hooks";
- defineOptions({
- name: "cl-loading"
- });
- // 定义组件属性
- const props = defineProps({
- // 透传样式
- pt: {
- type: Object,
- default: () => ({})
- },
- // 是否加载中
- loading: {
- type: Boolean,
- default: true
- },
- // 图标大小
- size: {
- type: [Number, String],
- default: 24
- },
- // 图标颜色
- color: {
- type: String,
- default: ""
- }
- });
- const { getPx } = useSize();
- // 透传样式类型定义
- type PassThrough = {
- className?: string;
- icon?: ClIconProps;
- };
- // 解析透传样式
- const pt = computed(() => parsePt<PassThrough>(props.pt));
- // 组件引用
- 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 start() {
- createAnimation(loadingRef.value, {
- duration: 2500,
- loop: -1,
- timingFunction: "linear"
- })
- .rotate("0deg", "360deg")
- .play();
- }
- // 组件挂载后监听loading状态
- onMounted(() => {
- watch(
- computed(() => props.loading),
- (val: boolean) => {
- // 当loading为true时开始旋转
- if (val) {
- start();
- }
- },
- {
- immediate: true
- }
- );
- });
- </script>
- <style lang="scss" scoped>
- .cl-loading {
- @apply flex flex-row items-center justify-center rounded-full;
- @apply border-surface-700 border-solid;
- &--dark {
- border-color: white !important;
- border-right-color: transparent !important;
- }
- }
- </style>
|