fix: optimize thumbnail animation

This commit is contained in:
Phan An 2022-07-16 17:44:45 +02:00
parent 6332abe74c
commit 05c298ca2c
No known key found for this signature in database
GPG key ID: A81E4477F0BB6FDC
14 changed files with 42 additions and 33 deletions

View file

@ -17,4 +17,4 @@ createApp(App)
*/ */
.mount('#app') .mount('#app')
navigator.serviceWorker.register('./sw.js').then(() => console.log('Service Worker Registered')) navigator.serviceWorker.register('./sw.js')

View file

@ -1,6 +1,6 @@
<template> <template>
<header id="mainHeader"> <header id="mainHeader">
<h1 class="brand">Koel</h1> <h1 class="brand text-thin">Koel</h1>
<span class="hamburger" role="button" title="Show or hide the sidebar" @click="toggleSidebar"> <span class="hamburger" role="button" title="Show or hide the sidebar" @click="toggleSidebar">
<icon :icon="faBars"/> <icon :icon="faBars"/>
</span> </span>
@ -54,7 +54,6 @@ const showAboutDialog = () => eventBus.emit('MODAL_SHOW_ABOUT_KOEL')
h1.brand { h1.brand {
flex: 1; flex: 1;
font-size: 1.7rem; font-size: 1.7rem;
font-weight: var(--font-weight-thin);
opacity: 0; opacity: 0;
line-height: var(--header-height); line-height: var(--header-height);
text-align: center; text-align: center;

View file

@ -1,6 +1,6 @@
<template> <template>
<section id="albumsWrapper"> <section id="albumsWrapper">
<ScreenHeader> <ScreenHeader layout="collapsed">
Albums Albums
<template v-slot:controls> <template v-slot:controls>
<ViewModeSwitch v-model="viewMode"/> <ViewModeSwitch v-model="viewMode"/>

View file

@ -1,6 +1,6 @@
<template> <template>
<section id="artistsWrapper"> <section id="artistsWrapper">
<ScreenHeader> <ScreenHeader layout="collapsed">
Artists Artists
<template v-slot:controls> <template v-slot:controls>
<ViewModeSwitch v-model="viewMode"/> <ViewModeSwitch v-model="viewMode"/>

View file

@ -1,6 +1,6 @@
<template> <template>
<section id="homeWrapper"> <section id="homeWrapper">
<ScreenHeader>{{ greeting }}</ScreenHeader> <ScreenHeader layout="collapsed">{{ greeting }}</ScreenHeader>
<div class="main-scroll-wrap" @scroll="scrolling"> <div class="main-scroll-wrap" @scroll="scrolling">
<ScreenEmptyState v-if="libraryEmpty"> <ScreenEmptyState v-if="libraryEmpty">

View file

@ -1,6 +1,6 @@
<template> <template>
<section id="uploadWrapper"> <section id="uploadWrapper">
<ScreenHeader> <ScreenHeader layout="collapsed">
Upload Media Upload Media
<template v-slot:controls> <template v-slot:controls>

View file

@ -1,6 +1,6 @@
<template> <template>
<section id="usersWrapper"> <section id="usersWrapper">
<ScreenHeader> <ScreenHeader layout="collapsed">
Users Users
<ControlsToggle :showing-controls="showingControls" @toggleControls="toggleControls"/> <ControlsToggle :showing-controls="showingControls" @toggleControls="toggleControls"/>

View file

@ -1,6 +1,6 @@
<template> <template>
<section id="youtubeWrapper"> <section id="youtubeWrapper">
<screen-header>{{ title }}</screen-header> <ScreenHeader layout="collapsed">{{ title }}</ScreenHeader>
<div id="player"> <div id="player">
<ScreenEmptyState data-testid="youtube-placeholder"> <ScreenEmptyState data-testid="youtube-placeholder">

View file

@ -1,7 +1,7 @@
<template> <template>
<section id="searchExcerptsWrapper"> <section id="searchExcerptsWrapper">
<ScreenHeader> <ScreenHeader layout="collapsed">
<span v-if="q">Search Results for <strong>{{ q }}</strong></span> <span v-if="q">Searching for <span class="text-thin">{{ q }}</span></span>
<span v-else>Search</span> <span v-else>Search</span>
</ScreenHeader> </ScreenHeader>

View file

@ -1,7 +1,7 @@
<template> <template>
<section id="songResultsWrapper"> <section id="songResultsWrapper">
<ScreenHeader :layout="headerLayout" has-thumbnail> <ScreenHeader :layout="headerLayout" has-thumbnail>
Songs for <span class="q">{{ decodedQ }}</span> Songs for <span class="text-thin">{{ decodedQ }}</span>
<ControlsToggle :showing-controls="showingControls" @toggleControls="toggleControls"/> <ControlsToggle :showing-controls="showingControls" @toggleControls="toggleControls"/>
<template v-slot:thumbnail> <template v-slot:thumbnail>
@ -62,9 +62,3 @@ const decodedQ = computed(() => decodeURIComponent(q.value))
searchStore.resetSongResultState() searchStore.resetSongResultState()
searchStore.songSearch(decodedQ.value) searchStore.songSearch(decodedQ.value)
</script> </script>
<style lang="scss" scoped>
.q {
font-weight: var(--font-weight-thin);
}
</style>

View file

@ -32,26 +32,28 @@ const { hasThumbnail } = toRefs(props)
<style lang="scss"> <style lang="scss">
header.screen-header { header.screen-header {
--transition-duration: .3s;
@media (prefers-reduced-motion) {
--transition-duration: 0;
}
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
border-bottom: 1px solid var(--color-bg-secondary); border-bottom: 1px solid var(--color-bg-secondary);
position: relative; position: relative;
align-content: stretch; align-content: stretch;
line-height: normal; line-height: normal;
gap: 1.5rem; padding: 1.8rem;
padding: .8rem 1rem .8rem 0;
will-change: height;
&.expanded { &.expanded {
padding: 1.8rem;
.thumbnail-wrapper { .thumbnail-wrapper {
margin-right: 1.5rem;
width: 192px; width: 192px;
}
h1.name { > * {
font-size: 4rem; transform: scale(1);
font-weight: bold; }
} }
.meta { .meta {
@ -66,13 +68,18 @@ header.screen-header {
.thumbnail-wrapper { .thumbnail-wrapper {
overflow: hidden; overflow: hidden;
width: 0;
display: none; display: none;
will-change: width, height; width: 0;
transition: width .3s; transition: width var(--transition-duration);
box-shadow: 0 10px 20px 0 rgba(0, 0, 0, 0.3); box-shadow: 0 10px 20px 0 rgba(0, 0, 0, 0.3);
border-radius: 5px; border-radius: 5px;
> * {
transform: scale(0);
transform-origin: bottom left;
transition: transform var(--transition-duration), width var(--transition-duration);
}
&.non-empty { &.non-empty {
display: block; display: block;
} }
@ -87,11 +94,12 @@ header.screen-header {
} }
h1.name { h1.name {
font-size: 2.75rem; font-size: 4rem;
font-weight: var(--font-weight-thin); font-weight: var(--font-weight-bold);
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
margin-right: 1.5rem;
} }
.heading-wrapper { .heading-wrapper {

View file

@ -1,5 +1,5 @@
<template> <template>
<div class="thumbnail-stack" :class="layout"> <div class="thumbnail-stack" :class="layout" :style="{ backgroundImage: `url(${defaultCover})` }">
<span v-for="thumbnail in displayedThumbnails" :style="{ backgroundImage: `url(${thumbnail}`}"/> <span v-for="thumbnail in displayedThumbnails" :style="{ backgroundImage: `url(${thumbnail}`}"/>
</div> </div>
</template> </template>
@ -26,6 +26,8 @@ const layout = computed<'mono' | 'tiles'>(() => displayedThumbnails.value.length
aspect-ratio: 1/1; aspect-ratio: 1/1;
display: grid; display: grid;
overflow: hidden; overflow: hidden;
background-size: cover;
background-repeat: no-repeat;
&.tiles { &.tiles {
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
@ -33,6 +35,7 @@ const layout = computed<'mono' | 'tiles'>(() => displayedThumbnails.value.length
span { span {
display: block; display: block;
will-change: transform; // fix anti-aliasing problem with background images
width: 100%; width: 100%;
height: 100%; height: 100%;
background-size: cover; background-size: cover;

View file

@ -277,6 +277,10 @@ label {
&uppercase { &uppercase {
text-transform: uppercase !important; text-transform: uppercase !important;
} }
&thin {
font-weight: var(--font-weight-thin) !important;
}
} }
.d- { .d- {

View file

@ -15,6 +15,7 @@
--font-weight-thin: 100; --font-weight-thin: 100;
--font-weight-light: 300; --font-weight-light: 300;
--font-weight-normal: 500; --font-weight-normal: 500;
--font-weight-bold: 700;
--header-height: 48px; --header-height: 48px;
--footer-height: 64px; --footer-height: 64px;