refactor: 悦码项目重构
This commit is contained in:
194
apps/platform/src/components/basic/lockscreen/huawei-charge.vue
Normal file
194
apps/platform/src/components/basic/lockscreen/huawei-charge.vue
Normal file
@@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<div class="huawei-charge">
|
||||
<div class="number">{{ battery.level.toFixed(0) }}%</div>
|
||||
<div class="contrast">
|
||||
<div class="circle" />
|
||||
<ul class="bubbles">
|
||||
<li v-for="i in 15" :key="i" />
|
||||
</ul>
|
||||
</div>
|
||||
<div class="charging">
|
||||
<div>{{ batteryStatus }}</div>
|
||||
<div v-show="Number.isFinite(battery.dischargingTime) && battery.dischargingTime != 0">
|
||||
剩余可使用时间:{{ calcDischargingTime }}
|
||||
</div>
|
||||
<span v-show="Number.isFinite(battery.chargingTime) && battery.chargingTime != 0">
|
||||
距离电池充满需要:{{ calcDischargingTime }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import type { PropType } from 'vue';
|
||||
import type { Battery } from '@/hooks/useBattery';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'HuaweiCharge',
|
||||
// props: ['batteryStatus', 'battery', 'calcDischargingTime'],
|
||||
props: {
|
||||
battery: {
|
||||
// 电池对象
|
||||
type: Object as PropType<Battery>,
|
||||
default: () => ({}),
|
||||
},
|
||||
calcDischargingTime: {
|
||||
// 电池剩余时间可用时间
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
batteryStatus: {
|
||||
// 电池状态
|
||||
type: String,
|
||||
validator: (val: string) => ['充电中', '已充满', '已断开电源'].includes(val),
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.huawei-charge {
|
||||
.generate-columns(15);
|
||||
|
||||
// @for $i from 0 through 15 {
|
||||
// li:nth-child(#{$i}) {
|
||||
// $width: 15 + random(15) + px;
|
||||
|
||||
// top: 50%;
|
||||
// left: 15 + random(70) + px;
|
||||
// width: $width;
|
||||
// height: $width;
|
||||
// transform: translate(-50%, -50%);
|
||||
// animation: ~'moveToTop `Math.random(6) + 3`s ease-in-out -`Math.random(5000) / 1000`s infinite';
|
||||
// }
|
||||
// }
|
||||
|
||||
@keyframes trotate {
|
||||
50% {
|
||||
border-radius: 45% / 42% 38% 58% 49%;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(-50%, -50%) rotate(720deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes move-to-top {
|
||||
90% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(-50%, -180px);
|
||||
opacity: 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hue-rotate {
|
||||
100% {
|
||||
filter: contrast(15) hue-rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
position: absolute;
|
||||
bottom: 20vh;
|
||||
left: 50vw;
|
||||
width: 300px;
|
||||
height: 400px;
|
||||
transform: translateX(-50%);
|
||||
.generate-columns(@n, @i: 0) when (@i =< @n) {
|
||||
.generate-columns(@n, (@i + 1));
|
||||
.column-@{i} {
|
||||
width: (@i * 100% / @n);
|
||||
}
|
||||
li:nth-child(@{i}) {
|
||||
@width: unit(~`Math.round(15 + Math.random() * 15) `, px);
|
||||
|
||||
top: 50%;
|
||||
left: unit(~`Math.round(Math.random() * 70) `, px);
|
||||
width: @width;
|
||||
height: @width;
|
||||
transform: translate(-50%, -50%);
|
||||
animation: move-to-top unit(~`(Math.round(Math.random() * 6) + 3) `, s) ease-in-out
|
||||
unit(~`-(Math.random() * 5000 / 1000) `, s) infinite;
|
||||
}
|
||||
}
|
||||
|
||||
.number {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
top: 27%;
|
||||
width: 300px;
|
||||
color: #fff;
|
||||
font-size: 32px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.contrast {
|
||||
width: 300px;
|
||||
height: 400px;
|
||||
overflow: hidden;
|
||||
animation: hue-rotate 10s infinite linear;
|
||||
background-color: #000;
|
||||
filter: contrast(15) hue-rotate(0);
|
||||
|
||||
.circle {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
filter: blur(8px);
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
transform: translate(-50%, -50%) rotate(0);
|
||||
animation: trotate 10s infinite linear;
|
||||
border-radius: 42% 38% 62% 49% / 45%;
|
||||
background-color: #00ff6f;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
width: 176px;
|
||||
height: 176px;
|
||||
transform: translate(-50%, -50%);
|
||||
border-radius: 50%;
|
||||
background-color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
.bubbles {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
transform: translate(-50%, 0);
|
||||
border-radius: 100px 100px 0 0;
|
||||
background-color: #00ff6f;
|
||||
filter: blur(5px);
|
||||
|
||||
li {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
background: #00ff6f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.charging {
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
3
apps/platform/src/components/basic/lockscreen/index.ts
Normal file
3
apps/platform/src/components/basic/lockscreen/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import LockScreen from './index.vue';
|
||||
|
||||
export { LockScreen };
|
||||
42
apps/platform/src/components/basic/lockscreen/index.vue
Normal file
42
apps/platform/src/components/basic/lockscreen/index.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<transition name="slide-up">
|
||||
<LockScreenPage v-if="isLock && isMouted && $route.name != LOGIN_NAME" />
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, onMounted } from 'vue';
|
||||
import LockScreenPage from './lockscreen-page.vue';
|
||||
import { useLockscreenStore } from '@/store/modules/lockscreen';
|
||||
import { LOGIN_NAME } from '@/router/constant';
|
||||
|
||||
const lockscreenStore = useLockscreenStore();
|
||||
const isLock = computed(() => lockscreenStore.isLock);
|
||||
const isMouted = ref(false);
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
isMouted.value = true;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.slide-up-enter-active {
|
||||
animation: slide-up 0.5s;
|
||||
}
|
||||
|
||||
.slide-up-leave-active {
|
||||
animation: slide-up 0.5s reverse;
|
||||
}
|
||||
|
||||
@keyframes slide-up {
|
||||
0% {
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,261 @@
|
||||
<template>
|
||||
<div
|
||||
:class="{ unLockLogin: isShowForm }"
|
||||
class="lockscreen"
|
||||
@keyup="isShowForm = true"
|
||||
@mousedown.stop
|
||||
@contextmenu.prevent
|
||||
>
|
||||
<template v-if="!isShowForm">
|
||||
<div class="lock-box">
|
||||
<div class="lock">
|
||||
<span class="lock-icon" title="解锁屏幕" @click="isShowForm = true">
|
||||
<Icon icon="ant-design:lock-outlined" size="30" />
|
||||
</span>
|
||||
</div>
|
||||
<h6 class="tips">点击解锁</h6>
|
||||
</div>
|
||||
<!-- 小米 / 华为 充电-->
|
||||
<component
|
||||
:is="BatteryComp"
|
||||
:battery="battery"
|
||||
:battery-status="batteryStatus"
|
||||
:calc-discharging-time="calcDischargingTime"
|
||||
/>
|
||||
<div class="local-time">
|
||||
<div class="time">{{ hour }}:{{ minute }}</div>
|
||||
<div class="date">{{ month }}月{{ day }}号,星期{{ week }}</div>
|
||||
</div>
|
||||
<div class="computer-status">
|
||||
<span :class="{ offline: !online }" class="network">
|
||||
<Icon icon="ant-design:wifi-outlined" size="30" class="network" />
|
||||
</span>
|
||||
<Icon icon="ant-design:api-outlined" size="30" />
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="login-box">
|
||||
<Avatar :size="80" :src="userStore.userInfo.avatar">
|
||||
<template #icon>
|
||||
<Icon icon="ant-design:user-outlined" size="50" />
|
||||
</template>
|
||||
</Avatar>
|
||||
<div class="username">{{ userStore.userInfo.username }}</div>
|
||||
<a-input-password v-model:value="password" autofocus :placeholder="pwdPlaceholder" />
|
||||
<div class="flex justify-between w-full">
|
||||
<template v-if="lockscreenStore.lockPwd">
|
||||
<a-button type="link" size="small" @click="hideLockForm">返回</a-button>
|
||||
<a-button type="link" size="small" @click="nav2login">返回登录</a-button>
|
||||
<a-button type="link" size="small" @click="onLogin">进入系统</a-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a-button type="link" size="small" @click="cancelLock">取消锁屏</a-button>
|
||||
<a-button type="link" size="small" @click="lockScreen">确定锁屏</a-button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineAsyncComponent, ref, computed } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { Avatar, message } from 'ant-design-vue';
|
||||
import { useOnline } from '@/hooks/useOnline';
|
||||
import { useTime } from '@/hooks/useTime';
|
||||
import { useBattery } from '@/hooks/useBattery';
|
||||
import { useLockscreenStore } from '@/store/modules/lockscreen';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import { LOGIN_NAME } from '@/router/constant';
|
||||
import { Icon } from '@/components/basic/icon';
|
||||
|
||||
const lockscreenStore = useLockscreenStore();
|
||||
const userStore = useUserStore();
|
||||
// const isLock = computed(() => lockscreenStore.isLock);
|
||||
// 获取本地时间
|
||||
const { month, day, hour, minute, week } = useTime();
|
||||
const { online } = useOnline();
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
||||
const { battery, batteryStatus, calcDischargingTime } = useBattery();
|
||||
|
||||
const BatteryComp = defineAsyncComponent(() => {
|
||||
return Math.random() > 0.49 ? import('./huawei-charge.vue') : import('./xiaomi-charge.vue');
|
||||
});
|
||||
|
||||
const isShowForm = ref(!lockscreenStore.lockPwd);
|
||||
const password = ref('');
|
||||
|
||||
const pwdPlaceholder = computed(() => {
|
||||
return lockscreenStore.lockPwd ? '请输入锁屏密码或用户密码' : '请输入锁屏密码(可选)';
|
||||
});
|
||||
|
||||
// 登录
|
||||
const onLogin = async () => {
|
||||
const pwd = password.value.trim();
|
||||
|
||||
if (pwd === '') return message.warn('密码不能为空');
|
||||
|
||||
if (lockscreenStore.verifyLockPwd(pwd)) {
|
||||
unlockScreen();
|
||||
} else {
|
||||
return message.warn('密码错误,请重新输入');
|
||||
}
|
||||
};
|
||||
|
||||
/** 隐藏锁屏输入表单 */
|
||||
const hideLockForm = () => {
|
||||
isShowForm.value = false;
|
||||
password.value = '';
|
||||
};
|
||||
|
||||
/** 取消锁屏 */
|
||||
const cancelLock = () => {
|
||||
isShowForm.value = false;
|
||||
lockscreenStore.setLock(false);
|
||||
};
|
||||
|
||||
// 确定锁屏
|
||||
const lockScreen = () => {
|
||||
const pwd = password.value.trim();
|
||||
lockscreenStore.setLockPwd(pwd);
|
||||
hideLockForm();
|
||||
};
|
||||
|
||||
// 取消锁屏/解锁锁屏
|
||||
const unlockScreen = () => {
|
||||
isShowForm.value = false;
|
||||
lockscreenStore.setLock(false);
|
||||
};
|
||||
// 输入密码 锁屏
|
||||
|
||||
const nav2login = () => {
|
||||
isShowForm.value = false;
|
||||
lockscreenStore.setLock(false);
|
||||
userStore.clearLoginStatus();
|
||||
router.replace({
|
||||
name: LOGIN_NAME,
|
||||
query: {
|
||||
redirect: route.fullPath,
|
||||
},
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.lockscreen {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
z-index: 9999;
|
||||
inset: 0;
|
||||
overflow: hidden;
|
||||
background: #000;
|
||||
color: white;
|
||||
|
||||
&.unLockLogin {
|
||||
background-color: rgb(25 28 34 / 78%);
|
||||
backdrop-filter: blur(7px);
|
||||
}
|
||||
|
||||
.setting-box,
|
||||
.login-box {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 45%;
|
||||
left: 50%;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 260px;
|
||||
transform: translate(-50%, -50%);
|
||||
|
||||
> * {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.username {
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
.lock-box {
|
||||
position: absolute;
|
||||
top: 12vh;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
font-size: 34px;
|
||||
|
||||
.tips {
|
||||
color: white;
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.lock {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.lock-icon {
|
||||
cursor: pointer;
|
||||
|
||||
.anticon-unlock {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover .anticon-unlock {
|
||||
display: initial;
|
||||
}
|
||||
|
||||
&:hover .anticon-lock {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.local-time {
|
||||
position: absolute;
|
||||
bottom: 60px;
|
||||
left: 60px;
|
||||
font-family: helvetica;
|
||||
|
||||
.time {
|
||||
font-size: 70px;
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.computer-status {
|
||||
position: absolute;
|
||||
right: 60px;
|
||||
bottom: 60px;
|
||||
font-size: 24px;
|
||||
|
||||
> * {
|
||||
margin-left: 14px;
|
||||
}
|
||||
|
||||
.network {
|
||||
position: relative;
|
||||
|
||||
&.offline::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 2px;
|
||||
height: 28px;
|
||||
transform: translate(-50%, -50%) rotate(45deg);
|
||||
background-color: red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
272
apps/platform/src/components/basic/lockscreen/xiaomi-charge.vue
Normal file
272
apps/platform/src/components/basic/lockscreen/xiaomi-charge.vue
Normal file
@@ -0,0 +1,272 @@
|
||||
<template>
|
||||
<div class="xiaomi-charge">
|
||||
<div v-for="i in 3" :key="i" class="outer">
|
||||
<div class="circle" :style="{ transform: `scale(${1.01 - 0.04 * (i - 1)})` }" />
|
||||
</div>
|
||||
<div class="line-box">
|
||||
<div class="line-left" />
|
||||
<div class="line-left line-right" />
|
||||
<div class="line-center line-center-left-2" />
|
||||
<div class="line-center line-center-left-1" />
|
||||
<div class="line-center" />
|
||||
<div class="line-center line-center-right-1" />
|
||||
<div class="line-center line-center-right-2" />
|
||||
</div>
|
||||
<div class="outer" style="transform: scale(0.68)">
|
||||
<div class="circle circle-blur" style="padding: 30px" />
|
||||
</div>
|
||||
<div v-for="i in 4" :key="i" class="outer">
|
||||
<div
|
||||
class="circle-white"
|
||||
:style="{
|
||||
transform: `scale(${1 - 0.02 * (i - 1)})`,
|
||||
animationDuration: `${500 - 20 * (i - 1)}ms`,
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
<div class="outer">
|
||||
<div class="text">{{ battery.level.toFixed(0) }}<span class="sub">%</span></div>
|
||||
</div>
|
||||
<div class="light" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import type { PropType } from 'vue';
|
||||
import type { Battery } from '@/hooks/useBattery';
|
||||
export default defineComponent({
|
||||
name: 'XiaomiCharge',
|
||||
props: {
|
||||
battery: {
|
||||
// 电池对象
|
||||
type: Object as PropType<Battery>,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.xiaomi-charge {
|
||||
@keyframes rotate {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes up {
|
||||
0% {
|
||||
transform: translateY(80px);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(-400px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes light {
|
||||
0% {
|
||||
transform: scale(0.3);
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: scale(1);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.3);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
display: flex;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50vw;
|
||||
justify-content: center;
|
||||
width: 300px;
|
||||
height: 400px;
|
||||
transform: translateX(-50%);
|
||||
|
||||
.circle {
|
||||
position: absolute;
|
||||
width: 286px;
|
||||
height: 286px;
|
||||
padding: 2px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(#c71ff1, #2554ea);
|
||||
}
|
||||
|
||||
.circle::after {
|
||||
content: ' ';
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.circle-blur {
|
||||
filter: blur(5px);
|
||||
animation: rotate 5s linear infinite;
|
||||
}
|
||||
|
||||
.circle-white {
|
||||
position: absolute;
|
||||
width: 220px;
|
||||
height: 220px;
|
||||
animation: rotate 500ms linear infinite;
|
||||
border-top: solid 1px rgb(255 255 255 / 6%);
|
||||
border-bottom: solid 1px rgb(255 255 255 / 8%);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.outer {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
bottom: 400px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.line-box {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 80px;
|
||||
height: 400px;
|
||||
overflow: hidden;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.line-left {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: -15px;
|
||||
box-sizing: border-box;
|
||||
width: 30px;
|
||||
height: 267px;
|
||||
border-top: solid 2px #2554ea;
|
||||
border-right: solid 2px #2554ea;
|
||||
border-top-right-radius: 40px;
|
||||
}
|
||||
|
||||
.line-left::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
left: 0;
|
||||
box-sizing: border-box;
|
||||
width: 30px;
|
||||
height: 100%;
|
||||
transform: scaleY(0.96);
|
||||
transform-origin: center top;
|
||||
border-top: solid 2px #2554ea;
|
||||
border-right: solid 2px #2554ea;
|
||||
border-top-right-radius: 50px;
|
||||
}
|
||||
|
||||
.line-left::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -14px;
|
||||
left: 0;
|
||||
box-sizing: border-box;
|
||||
width: 30px;
|
||||
height: 100%;
|
||||
transform: scaleY(0.92);
|
||||
transform-origin: center top;
|
||||
border-top: solid 2px #2554ea;
|
||||
border-right: solid 2px #2554ea;
|
||||
border-top-right-radius: 60px;
|
||||
}
|
||||
|
||||
.line-right {
|
||||
transform: scaleX(-1);
|
||||
transform-origin: 55px;
|
||||
}
|
||||
|
||||
.line-center {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 39px;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
background: #231779;
|
||||
}
|
||||
|
||||
.line-center::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
width: 2px;
|
||||
height: 80px;
|
||||
animation: up 700ms linear infinite;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
background: linear-gradient(#79ccea, transparent);
|
||||
}
|
||||
|
||||
.line-center-left-1 {
|
||||
transform: translateX(-9px);
|
||||
}
|
||||
|
||||
.line-center-left-2 {
|
||||
transform: translateX(-18px);
|
||||
}
|
||||
|
||||
.line-center-right-1 {
|
||||
transform: translateX(9px);
|
||||
}
|
||||
|
||||
.line-center-right-2 {
|
||||
transform: translateX(18px);
|
||||
}
|
||||
|
||||
.line-center-left-1::before {
|
||||
animation-delay: -200ms;
|
||||
}
|
||||
|
||||
.line-center-left-2::before {
|
||||
animation-delay: -400ms;
|
||||
}
|
||||
|
||||
.line-center-right-1::before {
|
||||
animation-delay: -300ms;
|
||||
}
|
||||
|
||||
.line-center-right-2::before {
|
||||
animation-delay: -500ms;
|
||||
}
|
||||
|
||||
.text {
|
||||
position: absolute;
|
||||
width: 200px;
|
||||
height: 80px;
|
||||
color: turquoise;
|
||||
font-size: 70px;
|
||||
line-height: 80px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sub {
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
.light {
|
||||
position: absolute;
|
||||
bottom: -150px;
|
||||
width: 300px;
|
||||
height: 350px;
|
||||
animation: light 1.2s linear 1 forwards;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(#2554ea, transparent 60%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user