mirror of
https://github.com/qier222/YesPlayMusic.git
synced 2024-11-25 02:01:40 +08:00
feat: add reversed mode & improvements to lyrics animation (#1226)
* feat(reversed-mode): add reversed mode & improvements to lyrics animation * feat(lyrics-animation): improve `:active` style * fix: extra white space after artist in lyrics view * refactor: remove unused function * feat: slightly add duration of transition to improve replication from Apple Music style
This commit is contained in:
parent
3ea5446fcc
commit
42f3da9b37
2
src/assets/icons/sort-up.svg
Normal file
2
src/assets/icons/sort-up.svg
Normal file
|
@ -0,0 +1,2 @@
|
|||
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="sort-amount-up" class="svg-inline--fa fa-sort-amount-up fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M304 416h-64a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h64a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h48v304a16 16 0 0 0 16 16h32a16 16 0 0 0 16-16V160h48c14.21 0 21.38-17.24 11.31-27.31l-80-96a16 16 0 0 0-22.62 0l-80 96C-5.35 142.74 1.77 160 16 160zm416 0H240a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h192a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm-64 128H240a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM496 32H240a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h256a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16z"></path></svg>
|
After Width: | Height: | Size: 784 B |
|
@ -132,6 +132,13 @@
|
|||
@click.native="player.switchShuffle"
|
||||
><svg-icon icon-class="shuffle"
|
||||
/></button-icon>
|
||||
<button-icon
|
||||
v-if="settings.enableReversedMode"
|
||||
:class="{ active: player.reversed, disabled: player.isPersonalFM }"
|
||||
:title="$t('player.reversed')"
|
||||
@click.native="player.switchReversed"
|
||||
><svg-icon icon-class="sort-up"
|
||||
/></button-icon>
|
||||
<div class="volume-control">
|
||||
<button-icon :title="$t('player.mute')" @click.native="player.mute">
|
||||
<svg-icon v-show="volume > 0.5" icon-class="volume" />
|
||||
|
|
|
@ -100,6 +100,7 @@ export default {
|
|||
repeat: 'Repeat',
|
||||
repeatTrack: 'Repeat Track',
|
||||
shuffle: 'Shuffle',
|
||||
reversed: 'Reversed',
|
||||
play: 'Play',
|
||||
pause: 'Pause',
|
||||
mute: 'Mute',
|
||||
|
@ -154,8 +155,9 @@ export default {
|
|||
showPlaylistsByAppleMusic: 'Show playlists by Apple Music',
|
||||
enableDiscordRichPresence: 'Enable Discord Rich Presence',
|
||||
enableGlobalShortcut: 'Enable Global Shortcut',
|
||||
showLibraryDefault: 'Show library default',
|
||||
subTitleDefault: 'Sub title alia default',
|
||||
showLibraryDefault: 'Show Library after App Launched',
|
||||
subTitleDefault: 'Show Alias for Subtitle by default',
|
||||
enableReversedMode: 'Enable Reversed Mode (Experimental)',
|
||||
lyricsBackground: {
|
||||
text: 'Show Lyrics Background',
|
||||
off: 'Off',
|
||||
|
|
|
@ -101,6 +101,7 @@ export default {
|
|||
repeat: '循环播放',
|
||||
repeatTrack: '单曲循环',
|
||||
shuffle: '随机播放',
|
||||
reversed: '倒序播放',
|
||||
play: '播放',
|
||||
pause: '暂停',
|
||||
mute: '静音',
|
||||
|
@ -157,6 +158,7 @@ export default {
|
|||
enableGlobalShortcut: '启用全局快捷键',
|
||||
showLibraryDefault: '启动后显示音乐库',
|
||||
subTitleDefault: '副标题使用别名',
|
||||
enableReversedMode: '启用倒序播放功能 (实验性功能)',
|
||||
lyricsBackground: {
|
||||
text: '显示歌词背景',
|
||||
off: '关闭',
|
||||
|
|
|
@ -97,6 +97,7 @@ export default {
|
|||
repeat: '循環播放',
|
||||
repeatTrack: '單曲循環',
|
||||
shuffle: '隨機播放',
|
||||
reversed: '倒序播放',
|
||||
play: '播放',
|
||||
pause: '暫停',
|
||||
mute: '靜音',
|
||||
|
@ -154,6 +155,7 @@ export default {
|
|||
enableGlobalShortcut: '啟用全域快捷鍵',
|
||||
showLibraryDefault: '啟動後顯示音樂庫',
|
||||
subTitleDefault: '副標題使用別名',
|
||||
enableReversedMode: '啟用倒序播放功能 (實驗性功能)',
|
||||
lyricsBackground: {
|
||||
text: '顯示歌詞背景',
|
||||
off: '關閉',
|
||||
|
|
|
@ -19,6 +19,7 @@ let localStorage = {
|
|||
enableUnblockNeteaseMusic: true,
|
||||
automaticallyCacheSongs: true,
|
||||
cacheLimit: 8192,
|
||||
enableReversedMode: false,
|
||||
nyancatStyle: false,
|
||||
showLyricsTranslation: true,
|
||||
lyricsBackground: true,
|
||||
|
|
|
@ -28,6 +28,7 @@ export default class {
|
|||
this._enabled = false; // 是否启用Player
|
||||
this._repeatMode = 'off'; // off | on | one
|
||||
this._shuffle = false; // true | false
|
||||
this._reversed = false;
|
||||
this._volume = 1; // 0 to 1
|
||||
this._volumeBeforeMuted = 1; // 用于保存静音前的音量
|
||||
this._personalFMLoading = false; // 是否正在私人FM中加载新的track
|
||||
|
@ -91,6 +92,18 @@ export default class {
|
|||
this._shuffleTheList();
|
||||
}
|
||||
}
|
||||
get reversed() {
|
||||
return this._reversed;
|
||||
}
|
||||
set reversed(reversed) {
|
||||
if (this._isPersonalFM) return;
|
||||
if (reversed !== true && reversed !== false) {
|
||||
console.warn('reversed: invalid args, must be Boolean');
|
||||
return;
|
||||
}
|
||||
console.log('changing reversed to:', reversed);
|
||||
this._reversed = reversed;
|
||||
}
|
||||
get volume() {
|
||||
return this._volume;
|
||||
}
|
||||
|
@ -191,27 +204,43 @@ export default class {
|
|||
}, 1000);
|
||||
}
|
||||
_getNextTrack() {
|
||||
const next = this._reversed ? this.current - 1 : this.current + 1;
|
||||
|
||||
if (this._playNextList.length > 0) {
|
||||
let trackID = this._playNextList.shift();
|
||||
return [trackID, this.current];
|
||||
}
|
||||
|
||||
// 当歌曲是列表最后一首 && 循环模式开启
|
||||
if (this.list.length === this.current + 1 && this.repeatMode === 'on') {
|
||||
return [this.list[0], 0];
|
||||
// 循环模式开启,则重新播放当前模式下的相对的下一首
|
||||
if (this.repeatMode === 'on') {
|
||||
if (this._reversed && this.current === 0) {
|
||||
// 倒序模式,当前歌曲是第一首,则重新播放列表最后一首
|
||||
return [this.list[this.list.length - 1], this.list.length - 1];
|
||||
} else if (this.list.length === this.current + 1) {
|
||||
// 正序模式,当前歌曲是最后一首,则重新播放第一首
|
||||
return [this.list[0], 0];
|
||||
}
|
||||
}
|
||||
|
||||
// 返回 [trackID, index]
|
||||
return [this.list[this.current + 1], this.current + 1];
|
||||
return [this.list[next], next];
|
||||
}
|
||||
_getPrevTrack() {
|
||||
// 当歌曲是列表第一首 && 循环模式开启
|
||||
if (this.current === 0 && this.repeatMode === 'on') {
|
||||
return [this.list[this.list.length - 1], this.list.length - 1];
|
||||
const next = this._reversed ? this.current + 1 : this.current - 1;
|
||||
|
||||
// 循环模式开启,则重新播放当前模式下的相对的下一首
|
||||
if (this.repeatMode === 'on') {
|
||||
if (this._reversed && this.current === 0) {
|
||||
// 倒序模式,当前歌曲是最后一首,则重新播放列表第一首
|
||||
return [this.list[0], 0];
|
||||
} else if (this.list.length === this.current + 1) {
|
||||
// 正序模式,当前歌曲是第一首,则重新播放列表最后一首
|
||||
return [this.list[this.list.length - 1], this.list.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
// 返回 [trackID, index]
|
||||
return [this.list[this.current - 1], this.current - 1];
|
||||
return [this.list[next], next];
|
||||
}
|
||||
async _shuffleTheList(firstTrackID = this._currentTrack.id) {
|
||||
let list = this._list.filter(tid => tid !== firstTrackID);
|
||||
|
@ -726,6 +755,9 @@ export default class {
|
|||
switchShuffle() {
|
||||
this.shuffle = !this.shuffle;
|
||||
}
|
||||
switchReversed() {
|
||||
this.reversed = !this.reversed;
|
||||
}
|
||||
|
||||
clearPlayNextList() {
|
||||
this._playNextList = [];
|
||||
|
|
|
@ -59,8 +59,8 @@
|
|||
<router-link
|
||||
:to="`/artist/${artist.id}`"
|
||||
@click.native="toggleLyrics"
|
||||
>{{ artist.name }}
|
||||
</router-link>
|
||||
>{{ artist.name }}</router-link
|
||||
>
|
||||
<span v-if="album.id !== 0">
|
||||
-
|
||||
<router-link
|
||||
|
@ -187,8 +187,18 @@
|
|||
}"
|
||||
@click="clickLyricLine(line.time)"
|
||||
@dblclick="clickLyricLine(line.time, true)"
|
||||
><span v-html="formatLine(line)"></span
|
||||
></div>
|
||||
>
|
||||
<span v-if="line.contents[0]">{{ line.contents[0] }}</span>
|
||||
<br />
|
||||
<span
|
||||
v-if="
|
||||
line.contents[1] &&
|
||||
$store.state.settings.showLyricsTranslation
|
||||
"
|
||||
class="translation"
|
||||
>{{ line.contents[1] }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
|
@ -400,16 +410,6 @@ export default {
|
|||
}
|
||||
}, 50);
|
||||
},
|
||||
formatLine(line) {
|
||||
const showLyricsTranslation = this.$store.state.settings
|
||||
.showLyricsTranslation;
|
||||
if (showLyricsTranslation && line.contents[1]) {
|
||||
return `<span>${line.contents[0]}<br/>${line.contents[1]}</span>`;
|
||||
} else if (line.contents[0] !== undefined) {
|
||||
return `<span>${line.contents[0]}</span>`;
|
||||
}
|
||||
return 'unknown';
|
||||
},
|
||||
moveToFMTrash() {
|
||||
this.player.moveToFMTrash();
|
||||
},
|
||||
|
@ -673,17 +673,28 @@ export default {
|
|||
scrollbar-width: none; // firefox
|
||||
|
||||
.line {
|
||||
padding: 18px;
|
||||
transition: 0.2s;
|
||||
margin: 2px 0;
|
||||
padding: 12px 18px;
|
||||
transition: 0.5s;
|
||||
border-radius: 12px;
|
||||
|
||||
&:hover {
|
||||
background: var(--color-secondary-bg-for-transparent);
|
||||
}
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
span {
|
||||
opacity: 0.28;
|
||||
cursor: default;
|
||||
font-size: 1em;
|
||||
transition: all 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
}
|
||||
|
||||
span.translation {
|
||||
opacity: 0.2;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -691,9 +702,19 @@ export default {
|
|||
background: unset;
|
||||
}
|
||||
|
||||
.translation {
|
||||
margin-top: 0.1em;
|
||||
}
|
||||
|
||||
.highlight span {
|
||||
opacity: 0.98;
|
||||
transition: 0.5s;
|
||||
display: inline-block;
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
.highlight span.translation {
|
||||
opacity: 0.65;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -755,6 +776,12 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1200px) {
|
||||
.right-side .lyrics-container {
|
||||
max-width: 600px;
|
||||
}
|
||||
}
|
||||
|
||||
.slide-up-enter-active,
|
||||
.slide-up-leave-active {
|
||||
transition: all 0.4s;
|
||||
|
|
|
@ -384,6 +384,23 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<div class="left">
|
||||
<div class="title">{{ $t('settings.enableReversedMode') }}</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="toggle">
|
||||
<input
|
||||
id="enable-reversed-mode"
|
||||
v-model="enableReversedMode"
|
||||
type="checkbox"
|
||||
name="enable-reversed-mode"
|
||||
/>
|
||||
<label for="enable-reversed-mode"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<div class="left">
|
||||
<div class="title" style="transform: scaleX(-1)">🐈️ 🏳️🌈</div>
|
||||
|
@ -805,6 +822,21 @@ export default {
|
|||
});
|
||||
},
|
||||
},
|
||||
enableReversedMode: {
|
||||
get() {
|
||||
if (this.settings.enableReversedMode === undefined) return false;
|
||||
return this.settings.enableReversedMode;
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('updateSettings', {
|
||||
key: 'enableReversedMode',
|
||||
value,
|
||||
});
|
||||
if (value === false) {
|
||||
this.$store.state.player.reversed = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
enableGlobalShortcut: {
|
||||
get() {
|
||||
return this.settings.enableGlobalShortcut;
|
||||
|
|
Loading…
Reference in New Issue
Block a user