Skip to content

Commit

Permalink
feat: offset time
Browse files Browse the repository at this point in the history
  • Loading branch information
CyanSalt committed Jan 19, 2024
1 parent 7db1c46 commit d5196ac
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 8 deletions.
31 changes: 23 additions & 8 deletions src/renderer/components/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { escapeHTML, splitSegments } from '../utils/string'
import KugouService from '../vendors/kugou'
import NeteaseService from '../vendors/netease'
import type { MusicData, MusicInfo, MusicService } from '../vendors/types'
import Slider from './Slider.vue'
let darkMode = $(useDarkMode())
let isFullscreen = $(useFullscreen())
Expand All @@ -20,6 +21,7 @@ let isAlwaysOnTop = $(useAlwaysOnTop())
let isPlaying = $ref(false)
let currentTime = $ref(0)
let offsetTime = $ref(0)
let service = $shallowRef<MusicService<any, any>>(NeteaseService)
let keyword = $ref('')
let info = $ref<MusicInfo>()
Expand All @@ -32,6 +34,8 @@ let connectedSong = $ref<any>()
const audio = $ref<HTMLAudioElement>()
const playingTime = $computed(() => currentTime + offsetTime)
const lyrics = $computed(() => {
if (!data) return []
return parseLRC(data.lyric)
Expand Down Expand Up @@ -76,16 +80,16 @@ const ANIMATION_TIME = 1
const CONNECTING_INTERVAL_TIME = 1
const currentIndex = $computed(() => {
return findLastIndex(lyrics, row => currentTime >= (row.time - ANIMATION_TIME))
return findLastIndex(lyrics, row => playingTime >= (row.time - ANIMATION_TIME))
})
// for performance
const lastIndex = $computed(() => {
return findLastIndex(lyrics, row => currentTime + CONNECTING_INTERVAL_TIME >= (row.time - ANIMATION_TIME))
return findLastIndex(lyrics, row => playingTime + CONNECTING_INTERVAL_TIME >= (row.time - ANIMATION_TIME))
})
const firstIndex = $computed(() => {
return findLastIndex(lyrics, row => currentTime - CONNECTING_INTERVAL_TIME >= (row.time - ANIMATION_TIME))
return findLastIndex(lyrics, row => playingTime - CONNECTING_INTERVAL_TIME >= (row.time - ANIMATION_TIME))
})
const indexes = $computed(() => {
Expand Down Expand Up @@ -242,6 +246,7 @@ async function prepare(song: any, detail: any, autoplay = false) {
if (!music) return
if (autoplay) {
currentTime = 0
offsetTime = 0
}
await nextTick()
if (audio) {
Expand Down Expand Up @@ -416,6 +421,7 @@ watchEffect(onInvalidate => {
</div>
</div>
</div>
<Slider v-if="data && !isPlaying" v-model="offsetTime" />
<audio
ref="audio"
:src="music"
Expand All @@ -432,6 +438,11 @@ watchEffect(onInvalidate => {
:global(body) {
margin: 0;
}
@keyframes fade-in {
from {
opacity: 0;
}
}
.app {
--foreground: black;
--background: white;
Expand All @@ -449,6 +460,15 @@ watchEffect(onInvalidate => {
&:not(.is-vibrant) {
background-color: var(--background);
}
:deep(.slider) {
position: fixed;
bottom: 1em;
left: 50%;
font-size: 48px;
transform: translateX(-50%);
transition: opacity 0.4s;
animation: fade-in 0.5s ease-in-out;
}
}
@keyframes shake {
0% {
Expand Down Expand Up @@ -495,11 +515,6 @@ watchEffect(onInvalidate => {
opacity: 0.25;
filter: blur(0.075em);
}
@keyframes fade-in {
from {
opacity: 0;
}
}
.next {
animation: fade-in 1s ease-in-out;
}
Expand Down
116 changes: 116 additions & 0 deletions src/renderer/components/Slider.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<script lang="ts" setup>
import { debounce } from 'lodash'
let modelValue = $(defineModel<number>({ default: 0 }))
const GRID_SIZE = 96 // 1in
let isActive = $ref(false)
const deactivate = debounce(() => {
isActive = false
}, 500)
function start(startingEvent: MouseEvent) {
let initialValue = modelValue
isActive = true
function handleMove(movingEvent: MouseEvent) {
modelValue = initialValue + (startingEvent.clientX - movingEvent.clientX) / GRID_SIZE
}
function handleUp(stoppingEvent: MouseEvent) {
deactivate()
modelValue = initialValue + (startingEvent.clientX - stoppingEvent.clientX) / GRID_SIZE
window.removeEventListener('mousemove', handleMove)
window.removeEventListener('mouseup', handleUp)
}
window.addEventListener('mousemove', handleMove, { passive: true })
window.addEventListener('mouseup', handleUp)
}
function reset() {
modelValue = 0
}
</script>

<template>
<div
:class="['slider', { 'is-active': isActive }]"
:style="{ '--position-offset': `calc(${modelValue * -1} * var(--grid-size))` }"
>
<div class="control" @mousedown="start" @dblclick="reset"></div>
<div class="track"></div>
</div>
</template>

<style lang="scss" scoped>
:global(body:has(.slider.is-active)) {
user-select: none;
}
.slider {
--slider-size: 50vw;
--base-offset: calc(var(--slider-size) / 2);
--position-offset: 0px;
--grid-size: 1in;
--guide-line-size: 8px;
--line-width: 2px;
position: relative;
display: flex;
align-items: center;
width: var(--slider-size);
height: 1em;
}
.control {
position: absolute;
top: 0;
left: 50%;
width: 1em;
height: 1em;
transform: translateX(-50%);
cursor: pointer;
&::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
margin-left: calc(var(--line-width) / 2);
border-width: 0 var(--guide-line-size) calc(var(--guide-line-size) * 2);
border-style: solid;
border-color: transparent transparent currentColor;
transform: translateX(-50%);
}
}
.track {
position: relative;
width: 100%;
height: calc(var(--guide-line-size) * 2);
background-image: linear-gradient(to right, currentColor, currentColor var(--line-width), transparent var(--line-width));
background-position-x: calc(var(--base-offset) + var(--position-offset));
background-position-y: calc(50% + var(--line-width) * 1.5);
background-size: var(--grid-size) var(--guide-line-size);
background-repeat: repeat-x;
opacity: 0;
transform: scaleY(-1);
transition: opacity 0.4s;
.slider.is-active & {
opacity: 1;
}
&::before {
content: '';
position: absolute;
inset: 0;
background-image: linear-gradient(to right, currentColor, currentColor var(--line-width), transparent var(--line-width));
background-position-x: calc(var(--base-offset) + var(--position-offset));
background-size: var(--grid-size) 100%;
background-repeat: no-repeat;
}
&::after {
content: '';
position: absolute;
inset: 0;
background-image: linear-gradient(to bottom, currentColor, currentColor var(--line-width), transparent var(--line-width));
background-position-y: calc(50% + var(--line-width) * 1.5);
background-size: 100% var(--guide-line-size);
background-repeat: no-repeat;
}
}
</style>

0 comments on commit d5196ac

Please sign in to comment.