优化动画效果,抽出组件

This commit is contained in:
algerkong
2021-07-21 15:01:39 +08:00
parent b55af4babd
commit 811152faa3
10 changed files with 437 additions and 305 deletions
+68
View File
@@ -0,0 +1,68 @@
<template>
<!-- 歌单分类列表 -->
<div class="play-list-type">
<div class="title animate__animated animate__fadeInLeft">歌单分类</div>
<n-layout class="bg-black">
<template v-for="(item, index) in playlistCategory?.sub" :key="item.name">
<span
class="play-list-type-item"
:class="setAnimationClass('animate__bounceIn')"
:style="setAnimationDelay(index <= 13 ? index : index - 13)"
v-if="isShowAllPlaylistCategory || index <= 13"
>{{ item.name }}</span>
</template>
<div
class="play-list-type-showall"
:class="setAnimationClass('animate__bounceIn')"
:style="
setAnimationDelay(
!isShowAllPlaylistCategory
? 25
: playlistCategory?.sub.length || 100 + 30
)
"
@click="isShowAllPlaylistCategory = !isShowAllPlaylistCategory"
>{{ !isShowAllPlaylistCategory ? "显示全部" : "隐藏一些" }}</div>
</n-layout>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from "vue";
import { getPlaylistCategory } from "@/api/home";
import type { IPlayListSort } from "@/type/playlist";
import { setAnimationDelay, setAnimationClass } from "@/utils";
// 歌单分类
const playlistCategory = ref<IPlayListSort>();
// 是否显示全部歌单分类
const isShowAllPlaylistCategory = ref<boolean>(false);
// 加载歌单分类
const loadPlaylistCategory = async () => {
const { data } = await getPlaylistCategory();
playlistCategory.value = data;
};
// 页面初始化
onMounted(() => {
loadPlaylistCategory();
});
</script>
<style lang="scss" scoped>
.title {
@apply text-lg font-bold mb-4;
}
.play-list-type {
width: 250px;
@apply mr-6;
&-item,
&-showall {
@apply py-2 px-3 mr-3 mb-3 inline-block border border-gray-700 rounded-xl cursor-pointer hover:bg-green-600 transition;
background-color: #1a1a1a;
}
&-showall {
@apply block text-center;
}
}
</style>
+70
View File
@@ -0,0 +1,70 @@
<template>
<!-- 推荐歌手 -->
<div class="recommend-singer">
<div class="recommend-singer-list">
<div
class="recommend-singer-item relative"
:class="setAnimationClass('animate__backInRight')"
v-for="(item, index) in hotSingerData?.artists"
:style="setAnimationDelay(index, 100)"
:key="item.id"
>
<div :style="setBackgroundImg(item.picUrl)" class="recommend-singer-item-bg"></div>
<div
class="recommend-singer-item-count p-2 text-base text-gray-200 z-10"
>{{ item.musicSize }}</div>
<div class="recommend-singer-item-info z-10">
<div class="recommend-singer-item-info-play">
<i class="iconfont icon-playfill text-xl"></i>
</div>
<div class="ml-4">
<div class="recommend-singer-item-info-name">{{ item.name }}</div>
<div class="recommend-singer-item-info-name">{{ item.name }}</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { setBackgroundImg, setAnimationDelay, setAnimationClass } from "@/utils";
import { onMounted, ref } from "vue";
import { getHotSinger } from "@/api/home";
import type { IHotSinger } from "@/type/singer";
// 歌手信息
const hotSingerData = ref<IHotSinger>();
//加载推荐歌手
const loadSingerList = async () => {
const { data } = await getHotSinger({ offset: 0, limit: 5 });
hotSingerData.value = data;
};
// 页面初始化
onMounted(() => {
loadSingerList();
});
</script>
<style lang="scss" scoped>
.recommend-singer {
&-list {
@apply flex;
height: 350px;
}
&-item {
@apply flex-1 h-full rounded-3xl p-5 mr-5 flex flex-col justify-between;
&-bg {
@apply bg-gray-900 bg-no-repeat bg-cover bg-center rounded-3xl absolute w-full h-full top-0 left-0 z-0;
filter: brightness(80%);
}
&-info {
@apply flex items-center p-2;
&-play {
@apply w-12 h-12 bg-green-500 rounded-full flex justify-center items-center hover:bg-green-600 cursor-pointer;
}
}
}
}
</style>
+52
View File
@@ -0,0 +1,52 @@
<template>
<div class="recommend-music">
<div class="title animate__animated animate__fadeInLeft">本周最热音乐</div>
<div
class="recommend-music-list"
:class="setAnimationClass('animate__bounceInUp')"
v-show="recommendMusic?.result"
>
<!-- 推荐音乐列表 -->
<template v-for="(item, index) in recommendMusic?.result" :key="item.id">
<song-item :item="item" :index="index" />
</template>
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from "vue";
import { getRecommendMusic } from "@/api/home";
import type { IRecommendMusic } from "@/type/music";
import { setAnimationClass } from "@/utils";
import SongItem from "./common/SongItem.vue";
// 推荐歌曲
const recommendMusic = ref<IRecommendMusic>();
// 加载推荐歌曲
const loadRecommendMusic = async () => {
const { data } = await getRecommendMusic({ limit: 10 });
recommendMusic.value = data;
};
// 页面初始化
onMounted(() => {
loadRecommendMusic();
});
</script>
<style lang="scss" scoped>
.title {
@apply text-lg font-bold mb-4;
}
.recommend-music {
.text-ellipsis {
width: 100%;
}
@apply flex-1 mr-96;
&-list {
@apply rounded-3xl p-2 w-full border border-gray-700;
background-color: #0d0d0d;
}
}
</style>
+91
View File
@@ -0,0 +1,91 @@
<template>
<div
class="recommend-music-list-item"
:class="setAnimationClass('animate__bounceInUp')"
:style="setAnimationDelay(index, 200)"
>
<img :src="item.picUrl" class="recommend-music-list-item-img" />
<div class="recommend-music-list-item-content">
<div class="recommend-music-list-item-content-title">
<n-ellipsis class="text-ellipsis" line-clamp="1">{{ item.song.name }}</n-ellipsis>
</div>
<div class="recommend-music-list-item-content-name">
<n-ellipsis class="text-ellipsis" line-clamp="1">{{ item.song.artists[0].name }}</n-ellipsis>
</div>
</div>
<div class="recommend-music-list-item-operating">
<div class="recommend-music-list-item-operating-like">
<i class="iconfont icon-likefill"></i>
</div>
<div class="recommend-music-list-item-operating-play" @click="playMusic(item)">
<i class="iconfont icon-playfill"></i>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { setAnimationDelay, setAnimationClass } from "@/utils";
import { useStore } from "vuex";
import type { SongResult } from "@/type/music";
import type { PropType } from "vue";
const props = defineProps({
item: {
type: Object as PropType<SongResult>,
required: true
},
index: {
type: Number,
required: true
}
})
const store = useStore();
const playMusic = (item: SongResult) => {
store.commit("setPlay", item);
store.commit("setIsPlay", true);
};
</script>
<style lang="scss" scoped>
.text-ellipsis {
width: 100%;
}
.recommend-music-list-item {
@apply rounded-3xl p-3 flex items-center hover:bg-gray-800 transition;
&-img {
@apply w-12 h-12 rounded-2xl mr-4;
}
&-content {
@apply flex-1;
&-title {
@apply text-base text-white;
}
&-name {
@apply text-xs;
@apply text-gray-400;
}
}
&-operating {
@apply flex items-center pl-4 rounded-full border border-gray-700;
background-color: #0d0d0d;
.iconfont {
@apply text-xl;
}
.icon-likefill {
color: #868686;
@apply text-xl hover:text-red-600 transition;
}
&-like {
@apply mr-2 cursor-pointer;
}
&-play {
@apply bg-black cursor-pointer border border-gray-500 rounded-full w-10 h-10 flex justify-center items-center hover:bg-green-600 transition;
}
}
}
</style>