feat: 优化一系列问题 #146

- 重构进入动画逻辑 #146
- 精简部分代码
- 优化部分动画
- 新增部分设置项
This commit is contained in:
imsyy 2023-08-16 18:24:10 +08:00
parent fe10751062
commit c12ddfb6b4
48 changed files with 502 additions and 458 deletions

View File

@ -17,9 +17,8 @@
<title>%VITE_SITE_NAME%</title>
<!-- HarmonyOS Sans -->
<!-- 本站 CDN 已开启防盗链,非本站域名不可访问,请更改链接为下方内容,否则自定义字体将失效 -->
<!-- https://s1.hdslb.com/bfs/static/jinkela/long/font/regular.css -->
<link rel="stylesheet" href="https://cdn.imsyy.top/gh/imsyy/file/font/HarmonyOS_Sans/regular.min.css" />
<link rel="stylesheet" href="/loading/loading.min.css">
<link rel="stylesheet" href="https://s1.hdslb.com/bfs/static/jinkela/long/font/regular.css" />
<!-- <link rel="stylesheet" href="https://cdn.imsyy.top/gh/imsyy/file/font/HarmonyOS_Sans/regular.min.css" /> -->
<!-- IE Out -->
<script>
if ( /*@cc_on!@*/ false || (!!window.MSInputMethodContext && !!document.documentMode))
@ -28,23 +27,7 @@
</script>
</head>
<body class="loading">
<!--加载动画-->
<div id="loading-box">
<div class="loading-left-bg"></div>
<div class="loading-right-bg"></div>
<div class="spinner-box">
<div class="loader">
<div class="inner one"></div>
<div class="inner two"></div>
<div class="inner three"></div>
</div>
<div class="loading-word">
<p class="loading-title" id="loading-title">%VITE_SITE_NAME%</p>
<span id="loading-text">加载中</span>
</div>
</div>
</div>
<body>
<!-- 主体内容 -->
<div id="app"></div>
<!-- noscript -->

View File

@ -4,7 +4,7 @@
"github": "https://github.com/imsyy/home",
"home": "https://imsyy.top",
"private": true,
"version": "4.0.5",
"version": "4.1.0",
"type": "module",
"scripts": {
"dev": "vite --host",

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

View File

@ -1,141 +0,0 @@
* {
margin: 0;
padding: 0;
}
#loading-box .loading-left-bg,
#loading-box .loading-right-bg {
position: fixed;
z-index: 999;
width: 50%;
height: 100%;
background-color: #515151e0;
transition: all 0.75s cubic-bezier(0.42, 0, 0, 1.01);
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
}
#loading-box .loading-right-bg {
right: 0;
}
#loading-box > .spinner-box {
position: fixed;
z-index: 999999;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100vh;
}
#loading-box .spinner-box .loading-word {
position: absolute;
color: #ffffff;
font-size: 0.95rem;
transform: translateY(64px);
text-align: center;
}
.loading-title {
font-size: 1.25rem;
margin: 20px 10px 4px 10px;
}
#loading-box .spinner-box .configure-core {
width: 100%;
height: 100%;
background-color: #37474f;
}
/* 加载完成 */
.loaded .loading-left-bg {
transform: translate(-100%, 0);
}
.loaded .loading-right-bg {
transform: translate(100%, 0);
}
.loaded .spinner-box {
display: none !important;
}
.loader {
position: absolute;
top: calc(50% - 32px);
left: calc(50% - 32px);
width: 64px;
height: 64px;
border-radius: 50%;
perspective: 800px;
transition: all 0.7s cubic-bezier(0.42, 0, 0, 1.01);
}
.inner {
position: absolute;
box-sizing: border-box;
width: 100%;
height: 100%;
border-radius: 50%;
}
.inner.one {
left: 0%;
top: 0%;
animation: rotate-one 1s linear infinite;
border-bottom: 3px solid #efeffa;
}
.inner.two {
right: 0%;
top: 0%;
animation: rotate-two 1s linear infinite;
border-right: 3px solid #efeffa;
}
.inner.three {
right: 0%;
bottom: 0%;
animation: rotate-three 1s linear infinite;
border-top: 3px solid #efeffa;
}
noscript {
z-index: 1000;
position: absolute;
display: flex;
justify-content: center;
width: 100%;
margin-top: 26px;
}
@keyframes rotate-one {
0% {
transform: rotateX(35deg) rotateY(-45deg) rotateZ(0deg);
}
100% {
transform: rotateX(35deg) rotateY(-45deg) rotateZ(360deg);
}
}
@keyframes rotate-two {
0% {
transform: rotateX(50deg) rotateY(10deg) rotateZ(0deg);
}
100% {
transform: rotateX(50deg) rotateY(10deg) rotateZ(360deg);
}
}
@keyframes rotate-three {
0% {
transform: rotateX(35deg) rotateY(55deg) rotateZ(0deg);
}
100% {
transform: rotateX(35deg) rotateY(55deg) rotateZ(360deg);
}
}

View File

@ -1 +0,0 @@
*{margin:0;padding:0}#loading-box .loading-left-bg,#loading-box .loading-right-bg{position:fixed;z-index:999;width:50%;height:100%;background-color:#515151e0;transition:all .75s cubic-bezier(.42,0,0,1.01);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}#loading-box .loading-right-bg{right:0}#loading-box>.spinner-box{position:fixed;z-index:999999;display:flex;justify-content:center;align-items:center;width:100%;height:100vh}#loading-box .spinner-box .loading-word{position:absolute;color:#fff;font-size:.95rem;transform:translateY(64px);text-align:center}.loading-title{font-size:1.25rem;margin:20px 10px 4px 10px}#loading-box .spinner-box .configure-core{width:100%;height:100%;background-color:#37474f}.loaded .loading-left-bg{transform:translate(-100%,0)}.loaded .loading-right-bg{transform:translate(100%,0)}.loaded .spinner-box{display:none!important}.loader{position:absolute;top:calc(50% - 32px);left:calc(50% - 32px);width:64px;height:64px;border-radius:50%;perspective:800px;transition:all .7s cubic-bezier(.42,0,0,1.01)}.inner{position:absolute;box-sizing:border-box;width:100%;height:100%;border-radius:50%}.inner.one{left:0;top:0;animation:rotate-one 1s linear infinite;border-bottom:3px solid #efeffa}.inner.two{right:0;top:0;animation:rotate-two 1s linear infinite;border-right:3px solid #efeffa}.inner.three{right:0;bottom:0;animation:rotate-three 1s linear infinite;border-top:3px solid #efeffa}noscript{z-index:1000;position:absolute;display:flex;justify-content:center;width:100%;margin-top:26px}@keyframes rotate-one{0%{transform:rotateX(35deg) rotateY(-45deg) rotateZ(0)}100%{transform:rotateX(35deg) rotateY(-45deg) rotateZ(360deg)}}@keyframes rotate-two{0%{transform:rotateX(50deg) rotateY(10deg) rotateZ(0)}100%{transform:rotateX(50deg) rotateY(10deg) rotateZ(360deg)}}@keyframes rotate-three{0%{transform:rotateX(35deg) rotateY(55deg) rotateZ(0)}100%{transform:rotateX(35deg) rotateY(55deg) rotateZ(360deg)}}

View File

@ -1,9 +1,13 @@
<template>
<div class="animate">
<Background />
<main>
<!-- 加载 -->
<Loading />
<!-- 壁纸 -->
<Background @loadComplete="loadComplete" />
<!-- 主界面 -->
<Transition name="fade" mode="out-in">
<main id="main" v-if="store.imgLoadStatus">
<div class="container" v-show="!store.backgroundShow">
<section class="main" v-show="!store.setOpenState">
<section class="all" v-show="!store.setOpenState">
<MainLeft />
<MainRight v-show="!store.boxOpenState" />
<Box v-show="store.boxOpenState" />
@ -24,26 +28,28 @@
>
<component :is="store.mobileOpenState ? CloseSmall : HamburgerButton" />
</Icon>
<!-- 页脚 -->
<Transition name="fade" mode="out-in">
<Footer v-show="!store.backgroundShow && !store.setOpenState" />
</Transition>
</main>
<Footer v-show="!store.backgroundShow && !store.setOpenState" />
</div>
</Transition>
</template>
<script setup>
import { onMounted, onBeforeUnmount, watch } from "vue";
import { onMounted, onBeforeUnmount, watch, nextTick } from "vue";
import { helloInit, checkDays } from "@/utils/getTime.js";
import { HamburgerButton, CloseSmall } from "@icon-park/vue-next";
import { mainStore } from "@/store";
import { Icon } from "@vicons/utils";
import { HamburgerButton, CloseSmall } from "@icon-park/vue-next";
import Loading from "@/components/Loading.vue";
import MainLeft from "@/views/Main/Left.vue";
import MainRight from "@/views/Main/Right.vue";
import Background from "@/components/Background/index.vue";
import Footer from "@/components/Footer/index.vue";
import Background from "@/components/Background.vue";
import Footer from "@/components/Footer.vue";
import Box from "@/views/Box/index.vue";
import MoreSet from "@/views/MoreSet/index.vue";
import cursorInit from "@/utils/cursor.js";
import config from "@/../package.json";
//
// import "@/utils/lantern.js";
const store = mainStore();
@ -52,22 +58,29 @@ const getWidth = () => {
store.setInnerWidth(window.innerWidth);
};
onMounted(() => {
//
cursorInit();
//
window.addEventListener("load", () => {
console.log("加载完成");
//
document.getElementsByTagName("body")[0].className = "";
//
const loadingBox = document.getElementById("loading-box");
loadingBox.classList.add("loaded");
//
const loadComplete = () => {
nextTick(() => {
//
helloInit();
//
checkDays();
});
};
//
watch(
() => store.innerWidth,
(value) => {
if (value < 990) {
store.boxOpenState = false;
}
}
);
onMounted(() => {
//
cursorInit();
//
document.oncontextmenu = () => {
@ -116,31 +129,23 @@ onMounted(() => {
);
});
//
watch(
() => store.innerWidth,
(value) => {
if (value < 990) {
store.boxOpenState = false;
}
}
);
onBeforeUnmount(() => {
window.removeEventListener("resize", getWidth);
});
</script>
<style lang="scss" scoped>
main {
#main {
transform: scale(1.2);
transition: transform 0.3s;
animation: fade-blur-main-in 0.65s cubic-bezier(0.25, 0.46, 0.45, 0.94)
forwards;
animation-delay: 0.5s;
.container {
width: 100%;
height: 100vh;
margin: 0 auto;
@media (max-width: 1200px) {
padding: 0 2vw;
}
.main {
.all {
width: 100%;
height: 100%;
padding: 0 0.75rem;
@ -158,8 +163,10 @@ main {
background-color: #00000080;
backdrop-filter: blur(20px);
z-index: 2;
animation: fade;
-webkit-animation: fade 0.5s;
animation: fade 0.5s;
}
@media (max-width: 1200px) {
padding: 0 2vw;
}
}
.menu {
@ -174,9 +181,8 @@ main {
background: rgb(0 0 0 / 20%);
backdrop-filter: blur(10px);
border-radius: 6px;
transition: all 0.3s;
animation: fade;
-webkit-animation: fade 0.5s;
transition: transform 0.3s;
animation: fade 0.5s;
&:active {
transform: scale(0.95);
}
@ -188,23 +194,4 @@ main {
}
}
}
//
.animate {
transform: scale(1);
transition: all ease 1.25s;
opacity: 1;
filter: blur(0);
width: 100%;
height: 100%;
}
.loading {
.animate {
transform: scale(1.2);
transition: all ease 1.25s;
opacity: 0;
filter: blur(10px);
}
}
</style>

View File

@ -1,33 +1,46 @@
<template>
<div class="cover">
<img class="bg" :src="bgUrl" alt="cover" />
<div :class="store.backgroundShow ? 'gray sm' : 'gray'" />
<transition name="el-fade-in-linear">
<img
v-show="store.imgLoadStatus"
class="bg"
alt="cover"
:src="bgUrl"
@load="imgLoadComplete"
@error.once="imgLoadError"
@animationend="imgAnimationEnd"
/>
<div :class="store.backgroundShow ? 'gray hidden' : 'gray'" />
<Transition name="fade" mode="out-in">
<a
v-if="store.backgroundShow && store.coverType != '3'"
class="down"
:href="bgUrl"
target="_blank"
v-show="store.backgroundShow && store.coverType != '3'"
>下载壁纸</a
>
</transition>
下载壁纸
</a>
</Transition>
</div>
</template>
<script setup>
import { onMounted, ref, watch, h } from "vue";
import { SuccessPicture } from "@icon-park/vue-next";
import { onMounted, onBeforeUnmount, ref, h } from "vue";
import { mainStore } from "@/store";
import { Error } from "@icon-park/vue-next";
const store = mainStore();
const bgUrl = ref(null); //
const bgUrl = ref(null);
const imgTimeout = ref(null);
const emit = defineEmits(["loadComplete"]);
//
// Math.random()
const bgRandom = Math.floor(Math.random() * 10 + 1);
//
const changeBg = (type) => {
if (type == 0) {
bgUrl.value = `/images/background${Math.floor(
Math.random() * 10 + 1
)}.webp`;
bgUrl.value = `/images/background${bgRandom}.jpg`;
} else if (type == 1) {
bgUrl.value = "https://api.dujin.org/bing/1920.php";
} else if (type == 2) {
@ -37,25 +50,41 @@ const changeBg = (type) => {
}
};
//
const imgLoadComplete = () => {
imgTimeout.value = setTimeout(() => {
store.setImgLoadStatus(true);
}, Math.floor(Math.random() * (600 - 300 + 1)) + 300);
};
//
const imgAnimationEnd = () => {
console.log("壁纸加载且动画完成");
//
emit("loadComplete");
};
//
const imgLoadError = () => {
console.error("壁纸加载失败:", bgUrl.value);
ElMessage({
message: "壁纸加载失败,已临时切换回默认",
icon: h(Error, {
theme: "filled",
fill: "#efefef",
}),
});
bgUrl.value = `/images/background${bgRandom}.jpg`;
};
onMounted(() => {
//
changeBg(store.coverType);
});
//
watch(
() => store.coverType,
(value) => {
changeBg(value);
ElMessage({
message: "壁纸设置成功",
icon: h(SuccessPicture, {
theme: "filled",
fill: "#efefef",
}),
});
}
);
onBeforeUnmount(() => {
clearTimeout(imgTimeout.value);
});
</script>
<style lang="scss" scoped>
@ -69,16 +98,17 @@ watch(
z-index: -1;
.bg {
transform: scale(1);
filter: blur(0);
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
object-fit: cover;
transition: all 1.5s ease 0s;
backface-visibility: hidden;
filter: blur(20px) brightness(0.3);
transition: filter 0.3s, transform 0.3s;
animation: fade-blur-in 1s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
animation-delay: 0.45s;
}
.gray {
opacity: 1;
@ -94,7 +124,7 @@ watch(
radial-gradient(rgba(0, 0, 0, 0) 33%, rgba(0, 0, 0, 0.3) 166%);
transition: 1.5s;
&.sm {
&.hidden {
opacity: 0;
transition: 1.5s;
}
@ -125,20 +155,4 @@ watch(
}
}
}
//
.loading {
.cover {
.bg {
transition: 1.5s;
transform: scale(1.1);
filter: blur(10px);
}
.gray {
transition: 1.5s;
opacity: 0;
}
}
}
</style>

108
src/components/Footer.vue Normal file
View File

@ -0,0 +1,108 @@
<template>
<footer id="footer" :class="store.footerBlur ? 'blur' : null">
<Transition name="fade" mode="out-in">
<div v-if="!store.playerState || !store.playerLrcShow" class="power">
<span>
Copyright&nbsp;&copy;
<span v-if="siteStartDate?.length >= 4" class="site-start">
{{ siteStartDate.substring(0, 4) }}
-
</span>
{{ fullYear }}
<a :href="SiteUrl">{{ SiteAnthor }}</a>
</span>
<!-- 以下信息请不要修改哦 -->
<span class="hidden">
&amp;&nbsp;Made&nbsp;by
<a :href="config.github" target="_blank">
{{ config.author }}
</a>
</span>
<!-- 站点备案 -->
<a v-if="siteIcp" href="https://beian.miit.gov.cn" target="_blank">
&amp;
{{ siteIcp }}
</a>
</div>
<div v-else class="lrc">
<Transition name="fade" mode="out-in">
<div class="lrc-all" :key="store.getPlayerLrc">
<music-one theme="filled" size="18" fill="#efefef" />
<span class="lrc-text text-hidden" v-html="store.getPlayerLrc" />
<music-one theme="filled" size="18" fill="#efefef" />
</div>
</Transition>
</div>
</Transition>
</footer>
</template>
<script setup>
import { ref } from "vue";
import { MusicOne } from "@icon-park/vue-next";
import { mainStore } from "@/store";
import config from "@/../package.json";
const store = mainStore();
const fullYear = new Date().getFullYear();
//
const siteStartDate = ref(import.meta.env.VITE_SITE_START);
const siteIcp = ref(import.meta.env.VITE_SITE_ICP);
const SiteAnthor = ref(import.meta.env.VITE_SITE_ANTHOR);
const SiteUrl = ref(import.meta.env.VITE_SITE_URL);
</script>
<style lang="scss" scoped>
#footer {
width: 100%;
position: absolute;
bottom: 0;
left: 0;
height: 46px;
line-height: 46px;
text-align: center;
z-index: 0;
.power {
animation: fade 0.3s;
}
.lrc {
padding: 0 20px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
.lrc-all {
width: 98%;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
.lrc-text {
margin: 0 8px;
}
.i-icon {
width: 18px;
height: 18px;
display: inherit;
}
}
}
&.blur {
backdrop-filter: blur(10px);
background: rgb(0 0 0 / 25%);
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.15s ease-in-out;
}
@media (max-width: 720px) {
font-size: 0.85rem;
}
@media (max-width: 480px) {
.hidden {
display: none;
}
}
}
</style>

View File

@ -1,101 +0,0 @@
<template>
<footer>
<div class="power" v-show="!store.playerState">
<span>
Copyright&nbsp;&copy;
<span v-if="siteStartDate?.length >= 4" class="site-start">
{{ siteStartDate.substring(0, 4) }}
-
</span>
{{ fullYear }}
<a :href="SiteUrl">{{ SiteAnthor }}</a>
</span>
<!-- 以下信息请不要修改哦 -->
<span class="hidden">
&amp;&nbsp;Made&nbsp;by
<a :href="config.github" target="_blank">
{{ config.author }}
</a>
</span>
<!-- 站点备案 -->
<a v-if="siteIcp" href="https://beian.miit.gov.cn" target="_blank">
&amp;
{{ siteIcp }}
</a>
</div>
<div class="lrc" v-show="store.playerState">
<music-one theme="filled" size="18" fill="#efefef" />
<span class="lrc-text">
{{ store.getPlayerLrc ? store.getPlayerLrc : "这句没有歌词" }}
</span>
<music-one theme="filled" size="18" fill="#efefef" />
</div>
</footer>
</template>
<script setup>
import { ref } from "vue";
import { MusicOne } from "@icon-park/vue-next";
import { mainStore } from "@/store";
import config from "@/../package.json";
const store = mainStore();
const fullYear = new Date().getFullYear();
//
const siteStartDate = ref(import.meta.env.VITE_SITE_START);
const siteIcp = ref(import.meta.env.VITE_SITE_ICP);
const SiteAnthor = ref(import.meta.env.VITE_SITE_ANTHOR);
const SiteUrl = ref(import.meta.env.VITE_SITE_URL);
</script>
<style lang="scss" scoped>
footer {
width: 100%;
position: absolute;
bottom: 0;
left: 0;
height: 46px;
line-height: 46px;
text-align: center;
backdrop-filter: blur(10px);
background: rgb(0 0 0 / 25%);
z-index: 0;
animation: fade;
-webkit-animation: fade 0.5s;
@media (max-width: 720px) {
font-size: 0.85rem;
}
@media (max-width: 480px) {
.hidden {
display: none;
}
}
.power {
animation: fade;
-webkit-animation: fade 0.3s;
}
.lrc {
padding: 0 20px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
animation: fade;
-webkit-animation: fade 0.3s;
.lrc-text {
margin: 0 8px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
word-break: break-all;
}
.i-icon {
width: 18px;
height: 18px;
display: inherit;
}
}
}
</style>

View File

@ -29,8 +29,9 @@
import { reactive, ref, onMounted, h } from "vue";
import { MusicMenu, Error } from "@icon-park/vue-next";
import { getHitokoto } from "@/api";
import debounce from "@/utils/debounce.js";
import { mainStore } from "@/store";
import debounce from "@/utils/debounce.js";
const store = mainStore();
//
@ -80,8 +81,7 @@ onMounted(() => {
width: 100%;
height: 100%;
padding: 20px;
animation: fade;
-webkit-animation: fade 0.5s;
animation: fade 0.5s;
.open-music {
width: 100%;
position: absolute;

View File

@ -34,7 +34,7 @@
<Icon size="26">
<component :is="siteIcon[item.icon]" />
</Icon>
<span class="name">{{ item.name }}</span>
<span class="name text-hidden">{{ item.name }}</span>
</div>
</el-col>
</el-row>
@ -109,8 +109,7 @@ onMounted(() => {
font-size: 1.1rem;
display: flex;
align-items: center;
animation: fade;
-webkit-animation: fade 0.5s;
animation: fade 0.5s;
.title {
margin-left: 8px;
font-size: 1.15rem;
@ -149,8 +148,8 @@ onMounted(() => {
align-items: center;
flex-direction: row;
justify-content: center;
animation: fade;
-webkit-animation: fade 0.5s;
padding: 0 10px;
animation: fade 0.5s;
&:hover {
transform: scale(1.02);

150
src/components/Loading.vue Normal file
View File

@ -0,0 +1,150 @@
<template>
<div id="loader-wrapper" :class="store.imgLoadStatus ? 'loaded' : null">
<div class="loader">
<div class="loader-circle" />
<div class="loader-text">
<span class="name">
{{ siteName }}
</span>
<span class="tip"> 加载中 </span>
</div>
</div>
<div class="loader-section section-left" />
<div class="loader-section section-right" />
</div>
</template>
<script setup>
import { mainStore } from "@/store";
const store = mainStore();
//
const siteName = import.meta.env.VITE_SITE_NAME;
</script>
<style lang="scss" scoped>
#loader-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999;
overflow: hidden;
.loader {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.loader-circle {
width: 150px;
height: 150px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #fff;
animation: spin 1.8s linear infinite;
z-index: 2;
&:before {
content: "";
position: absolute;
top: 5px;
left: 5px;
right: 5px;
bottom: 5px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #a4a4a4;
animation: spin-reverse 0.6s linear infinite;
}
&:after {
content: "";
position: absolute;
top: 15px;
left: 15px;
right: 15px;
bottom: 15px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #d3d3d3;
animation: spin 1s linear infinite;
}
}
.loader-text {
display: flex;
flex-direction: column;
align-items: center;
color: #fff;
z-index: 2;
margin-top: 40px;
font-size: 24px;
.tip {
margin-top: 6px;
font-size: 18px;
opacity: 0.6;
}
}
}
.loader-section {
position: fixed;
top: 0;
width: 51%;
height: 100%;
background: #333;
z-index: 1;
&.section-left {
left: 0;
}
&.section-right {
right: 0;
}
}
&.loaded {
visibility: hidden;
transform: translateY(-100%);
transition: transform 0.3s 1s ease-out, visibility 0.3s 1s ease-out;
.loader {
.loader-circle,
.loader-text {
opacity: 0;
transition: opacity 0.3s ease-out;
}
}
.loader-section {
&.section-left {
transform: translateX(-100%);
transition: transform 0.5s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
&.section-right {
transform: translateX(100%);
transition: transform 0.5s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
}
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes spin-reverse {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-360deg);
}
}
</style>

View File

@ -83,8 +83,7 @@ watch(
display: flex;
flex-direction: row;
align-items: center;
animation: fade;
-webkit-animation: fade 0.5s;
animation: fade 0.5s;
.logo-img {
border-radius: 50%;
width: 120px;
@ -125,8 +124,7 @@ watch(
padding: 1rem;
margin-top: 3.5rem;
max-width: 460px;
animation: fade;
-webkit-animation: fade 0.5s;
animation: fade 0.5s;
.content {
display: flex;

View File

@ -93,7 +93,7 @@
:songType="playerData.type"
:songId="playerData.id"
:volume="volumeNum"
:shuffle="true"
:shuffle="false"
ref="playerRef"
/>
</div>
@ -114,7 +114,7 @@ import {
VolumeSmall,
VolumeNotice,
} from "@icon-park/vue-next";
import Player from "@/components/Player/index.vue";
import Player from "@/components/Player.vue";
import { mainStore } from "@/store";
const store = mainStore();
@ -179,8 +179,7 @@ watch(
justify-content: space-between;
align-items: center;
flex-direction: column;
animation: fade;
-webkit-animation: fade 0.5s;
animation: fade 0.5s;
.btns {
display: flex;
align-items: center;
@ -242,8 +241,7 @@ watch(
text-overflow: ellipsis;
overflow-x: hidden;
white-space: nowrap;
animation: fade;
-webkit-animation: fade 0.3s;
animation: fade 0.3s;
}
.volume {
width: 100%;
@ -251,8 +249,7 @@ watch(
display: flex;
align-items: center;
flex-direction: row;
animation: fade;
-webkit-animation: fade 0.3s;
animation: fade 0.3s;
.icon {
margin-right: 12px;
span {

View File

@ -20,12 +20,11 @@
</template>
<script setup>
import aplayer from "vue3-aplayer";
import fetchJsonp from "fetch-jsonp";
import { h, ref, nextTick, onMounted } from "vue";
import { MusicOne, PlayWrong } from "@icon-park/vue-next";
import { getPlayerList } from "@/api";
import { mainStore } from "@/store";
import aplayer from "vue3-aplayer";
const store = mainStore();
@ -34,7 +33,6 @@ const player = ref(null);
//
const playList = ref([]);
const playerLrc = ref("");
//
const playIndex = ref(0);
@ -70,10 +68,10 @@ const props = defineProps({
return value >= 0 && value <= 1;
},
},
// ( netease-, tencent-qq, kugou-, xiami-, baidu- )
// ( netease-, tencent-qq )
songServer: {
type: String,
default: "netease", //'netease' | 'tencent' | 'kugou' | 'xiami' | 'baidu'
default: "netease", //'netease' | 'tencent'
},
// ( song-, playlist-, album-, search-, artist- )
songType: {
@ -143,7 +141,7 @@ onMounted(() => {
});
});
//
//
const onPlay = () => {
console.log("播放");
//
@ -162,6 +160,8 @@ const onPlay = () => {
}),
});
};
//
const onPause = () => {
store.setPlayerState(player.value.audio.paused);
};
@ -170,10 +170,13 @@ const onPause = () => {
const onTimeUp = () => {
let playerRef = player.value.$.vnode.el;
if (playerRef) {
playerLrc.value = playerRef.getElementsByClassName(
"aplayer-lrc-current"
)[0].innerHTML;
store.setPlayerLrc(playerLrc.value);
const currentLrcElement = playerRef.querySelector(".aplayer-lrc-current");
const previousLrcElement = currentLrcElement?.previousElementSibling;
const lrcContent =
currentLrcElement?.innerHTML ||
previousLrcElement?.innerHTML ||
"这句没有歌词";
store.setPlayerLrc(lrcContent);
}
};

View File

@ -11,7 +11,7 @@
</el-radio-group>
</div>
</el-collapse-item>
<el-collapse-item title="其他设置" name="2">
<el-collapse-item title="个性设置" name="2">
<div class="item">
<span class="text">建站日期显示</span>
<el-switch
@ -30,6 +30,24 @@
:inactive-icon="CloseSmall"
/>
</div>
<div class="item">
<span class="text">底栏歌词显示</span>
<el-switch
v-model="playerLrcShow"
inline-prompt
:active-icon="CheckSmall"
:inactive-icon="CloseSmall"
/>
</div>
<div class="item">
<span class="text">底栏是否模糊</span>
<el-switch
v-model="footerBlur"
inline-prompt
:active-icon="CheckSmall"
:inactive-icon="CloseSmall"
/>
</div>
</el-collapse-item>
<el-collapse-item title="其他设置" name="3">
<div>设置内容待增加</div>
@ -48,7 +66,8 @@ import { CheckSmall, CloseSmall } from "@icon-park/vue-next";
import { storeToRefs } from "pinia";
const store = mainStore();
const { siteStartShow, musicClick } = storeToRefs(store);
const { siteStartShow, musicClick, playerLrcShow, footerBlur } =
storeToRefs(store);
//
const activeName = ref("1");

View File

@ -37,9 +37,8 @@ const socialTip = ref("通过这里联系我吧");
background-color: transparent;
border-radius: 6px;
backdrop-filter: blur(0);
animation: fade;
-webkit-animation: fade 0.5s;
transition: all 0.5s;
animation: fade 0.5s;
transition: background-color 0.3s, backdrop-filter 0.3s;
@media (max-width: 840px) {
max-width: 100%;
justify-content: center;
@ -60,9 +59,12 @@ const socialTip = ref("通过这里联系我吧");
display: inherit;
.icon {
margin: 0 12px;
transition: all 0.3s;
transition: transform 0.3s;
&:hover {
transform: scale(1.1);
}
&:active {
transform: scale(0.9);
transform: scale(1);
}
}
}
@ -70,8 +72,7 @@ const socialTip = ref("通过这里联系我吧");
.tip {
display: none;
margin-right: 12px;
animation: fade;
-webkit-animation: fade 0.5s;
animation: fade 0.5s;
}
@media (min-width: 768px) {
&:hover {

View File

@ -3,9 +3,11 @@ import { defineStore } from "pinia";
export const mainStore = defineStore("main", {
state: () => {
return {
imgLoadStatus: false, // 壁纸加载状态
innerWidth: null, // 当前窗口宽度
coverType: "0", // 壁纸种类
siteStartShow: true, // 建站日期显示
musicClick: false, // 音乐链接是否跳转
musicIsOk: false, // 音乐是否加载完成
musicVolume: 0, // 音乐音量;
musicOpenState: false, // 音乐面板开启状态
@ -18,7 +20,8 @@ export const mainStore = defineStore("main", {
playerTitle: null, // 当前播放歌曲名
playerArtist: null, // 当前播放歌手名
playerLrc: "歌词加载中", // 当前播放歌词
musicClick: false, // 音乐链接是否跳转
playerLrcShow: true, // 是否显示底栏歌词
footerBlur: true, // 底栏模糊
};
},
getters: {
@ -64,10 +67,21 @@ export const mainStore = defineStore("main", {
this.playerTitle = title;
this.playerArtist = artist;
},
// 更改壁纸加载状态
setImgLoadStatus(value) {
this.imgLoadStatus = value;
},
},
persist: {
key: "data",
storage: window.localStorage,
paths: ["coverType", "musicVolume", "siteStartShow", "musicClick"],
paths: [
"coverType",
"musicVolume",
"siteStartShow",
"musicClick",
"playerLrcShow",
"footerBlur",
],
},
});

View File

@ -17,9 +17,9 @@
}
}
/* 小于1200px时 */
@media (max-width: 1200px) {
@include changeWidth($maxWidth:1000px);
/* 小于1280px时 */
@media (max-width: 1280px) {
@include changeWidth($maxWidth:1100px);
}
/* 小于992px时 */

View File

@ -59,19 +59,16 @@ p {
// 卡片样式
.cards {
border-radius: 6px;
background: #00000040;
-webkit-backdrop-filter: blur(10px);
background-color: #00000040;
backdrop-filter: blur(10px);
transform: scale(1);
transition: all 0.3s;
}
.cards:hover {
transform: scale(1.01);
}
.cards:active {
transform: scale(0.98);
transition: backdrop-filter 0.3s, transform 0.3s;
&:hover {
transform: scale(1.01);
}
&:active {
transform: scale(0.98);
}
}
// 文字超出
@ -103,13 +100,11 @@ p {
.el-progress-bar__outer {
border-radius: 6px;
background-color: #00000020;
.el-progress-bar__inner {
background-color: #efefef;
border-radius: 6px;
text-align: center;
font-family: "UnidreamLED";
span {
color: #564d59;
font-size: 0.9rem;
@ -129,31 +124,59 @@ p {
border-radius: 8px !important;
border: 1px solid transparent !important;
background-color: transparent !important;
.el-card__header {
font-weight: bold;
padding: 16px 20px !important;
background-color: #ffffff30 !important;
border-bottom: 1px solid transparent !important;
}
.el-card__body {
padding: 0 !important;
background-color: #ffffff10 !important;
}
}
// 渐入动画
// Transition 动画
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease-in-out;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
// keyframes 动画
@keyframes fade {
0% {
from {
opacity: 0;
}
100% {
to {
opacity: 1;
}
}
@keyframes fade-blur-in {
from {
filter: blur(20px) brightness(0.3);
transform: scale(1.6);
}
to {
filter: blur(0) brightness(1);
transform: scale(1.2);
}
}
@keyframes fade-blur-main-in {
from {
transform: scale(1.2);
}
to {
transform: scale(1);
}
}
// 隐藏元素
@media (min-width: 910px) and (max-width: 1200px) {
.sm-hidden {

View File

@ -1,6 +0,0 @@
/*!
* china-lantern v1.6.0
* (c) 2020-2021 fz6m
* Released under the MIT License.
*/
!function(t){"function"==typeof define&&define.amd?define(t):t()}((function(){"use strict";!function(t,e){void 0===e&&(e={});var n=e.insertAt;if(t&&"undefined"!=typeof document){var r=document.head||document.getElementsByTagName("head")[0],a=document.createElement("style");a.type="text/css","top"===n&&r.firstChild?r.insertBefore(a,r.firstChild):r.appendChild(a),a.styleSheet?a.styleSheet.cssText=t:a.appendChild(document.createTextNode(t))}}('@charset "UTF-8";.lantern__warpper{position:fixed;top:12px;left:40px;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:999}.lantern__warpper.lantern__secondary{left:calc(100% - 130px)}.lantern__warpper.lantern__secondary .lantern__box{-webkit-animation-duration:3s;animation-duration:3s;animation-delay:1s;}.lantern__box{position:relative;display:inline-block;width:90px;height:70px;background:rgba(216,0,15,.8);border-radius:50% 50%;animation:lantern-swing 3s ease-in-out infinite alternate-reverse;-webkit-transform-origin:50% -70px;-ms-transform-origin:50% -70px;transform-origin:50% -70px;-webkit-box-shadow:-5px 5px 50px 4px #fa6c00;box-shadow:-5px 5px 50px 4px #fa6c00}.lantern__box:after,.lantern__box:before{content:"";position:absolute;height:8px;width:45px;left:50%;border:1px solid #dc8f03;background:-webkit-gradient(linear,left top,right top,from(#dc8f03),color-stop(orange),color-stop(#dc8f03),color-stop(orange),to(#dc8f03));background:-o-linear-gradient(left,#dc8f03,orange,#dc8f03,orange,#dc8f03);background:linear-gradient(90deg,#dc8f03,orange,#dc8f03,orange,#dc8f03)}.lantern__box:before{top:0;border-radius:5px 5px 0 0;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.lantern__box:after{bottom:0;border-radius:0 0 5px 5px;-webkit-transform:translate(-50%,50%);-ms-transform:translate(-50%,50%);transform:translate(-50%,50%)}.lantern__line{position:absolute;width:2px;height:12px;top:0;left:50%;-webkit-transform:translate(-50%,-100%);-ms-transform:translate(-50%,-100%);transform:translate(-50%,-100%);background:#dc8f03}.lantern__circle{width:80%;-webkit-box-sizing:border-box;box-sizing:border-box}.lantern__circle,.lantern__circle .lantern__ellipse{height:100%;margin:0 auto;border-radius:50%;border:2px solid #dc8f03}.lantern__circle .lantern__ellipse{width:50%}.lantern__circle .lantern__text{font-family:华文行楷,Microsoft YaHei,sans-serif;font-size:24.3px;color:#dc8f03;font-weight:700;line-height:66px;text-align:center}.lantern__tail{position:relative;width:4px;height:12px;margin:0 auto;animation:lantern-swing 4s ease-in-out infinite alternate-reverse;background:orange;border-radius:0 0 5px 5px}.lantern__tail .lantern__junction{position:absolute;top:0;left:50%;width:8px;height:8px;-webkit-transform:translate(-50%,8.4px);-ms-transform:translate(-50%,8.4px);transform:translate(-50%,8.4px);background:#e69603;border-radius:50%}.lantern__tail .lantern__rect{position:absolute;top:0;left:50%;-webkit-transform:translate(-50%,10.8px);-ms-transform:translate(-50%,10.8px);transform:translate(-50%,10.8px);width:8px;height:24px;background:orange;border-radius:5px 5px 0 5px}@-webkit-keyframes lantern-swing{0%{-webkit-transform:rotate(-8deg);transform:rotate(-8deg)}to{-webkit-transform:rotate(8deg);transform:rotate(8deg)}}@keyframes lantern-swing{0%{-webkit-transform:rotate(-8deg);transform:rotate(-8deg)}to{-webkit-transform:rotate(8deg);transform:rotate(8deg)}}@media (max-width:520px){.j-china-lantern{display: none;}');var t;(t=document.createElement("div")).className="j-china-lantern",t.innerHTML='<div class="lantern__warpper"><div class="lantern__box"><div class="lantern__line"></div><div class="lantern__circle"><div class="lantern__ellipse"><div class="lantern__text">新</div></div></div><div class="lantern__tail"><div class="lantern__rect"></div><div class="lantern__junction"></div></div></div></div><div class="lantern__warpper lantern__secondary"><div class="lantern__box"><div class="lantern__line"></div><div class="lantern__circle"><div class="lantern__ellipse"><div class="lantern__text">年</div></div></div><div class="lantern__tail"><div class="lantern__rect"></div><div class="lantern__junction"></div></div></div></div>',document.body.appendChild(t)}));

View File

@ -34,7 +34,7 @@
import { ref } from "vue";
import { CloseOne, SettingTwo } from "@icon-park/vue-next";
import { mainStore } from "@/store";
import TimeCapsule from "@/components/TimeCapsule/index.vue";
import TimeCapsule from "@/components/TimeCapsule.vue";
const store = mainStore();
const closeShow = ref(false);
@ -46,8 +46,7 @@ const closeShow = ref(false);
margin-left: 0.75rem;
height: 80%;
position: relative;
animation: fade;
-webkit-animation: fade 0.5s;
animation: fade 0.5s;
&:hover {
transform: scale(1);

View File

@ -36,9 +36,9 @@
import { ref, onMounted, onBeforeUnmount } from "vue";
import { getCurrentTime } from "@/utils/getTime";
import { mainStore } from "@/store";
import Music from "@/components/Music/index.vue";
import Hitokoto from "@/components/Hitokoto/index.vue";
import Weather from "@/components/Weather/index.vue";
import Music from "@/components/Music.vue";
import Hitokoto from "@/components/Hitokoto.vue";
import Weather from "@/components/Weather.vue";
const store = mainStore();
@ -114,8 +114,7 @@ onBeforeUnmount(() => {
flex-direction: column;
align-items: center;
justify-content: space-between;
animation: fade;
-webkit-animation: fade 0.5s;
animation: fade 0.5s;
.time {
font-size: 1.1rem;
text-align: center;

View File

@ -7,8 +7,8 @@
<script setup>
import { mainStore } from "@/store";
import Message from "@/components/Message/index.vue";
import SocialLinks from "@/components/SocialLinks/index.vue";
import Message from "@/components/Message.vue";
import SocialLinks from "@/components/SocialLinks.vue";
const store = mainStore();
</script>

View File

@ -15,7 +15,7 @@
<script setup>
import { mainStore } from "@/store";
import Func from "@/views/Func/index.vue";
import Link from "@/components/Links/index.vue";
import Link from "@/components/Links.vue";
const store = mainStore();
//
@ -36,9 +36,8 @@ const siteUrl = import.meta.env.VITE_SITE_URL.split(".");
top: 6%;
left: 0;
text-align: center;
transition: all 0.3s;
animation: fade;
-webkit-animation: fade 0.5s;
transition: transform 0.3s;
animation: fade 0.5s;
&:active {
transform: scale(0.95);
}

View File

@ -75,10 +75,10 @@ import {
Bug,
} from "@icon-park/vue-next";
import { mainStore } from "@/store";
import Set from "@/components/Set/index.vue";
import Set from "@/components/Set.vue";
import config from "@/../package.json";
const store = mainStore();
const store = mainStore();
const closeShow = ref(false);
//

View File

@ -91,7 +91,7 @@ export default ({ mode }) =>
],
server: {
port: "3000",
hmr: true,
open: true,
},
resolve: {
alias: [