v2.0.0
This commit is contained in:
@@ -0,0 +1,353 @@
|
||||
<template>
|
||||
<div :class="['right', $style.right]" :style="lrcFontSize">
|
||||
<transition enter-active-class="animated fadeIn" leave-active-class="animated fadeOut">
|
||||
<div
|
||||
v-show="!isShowLrcSelectContent"
|
||||
ref="dom_lyric"
|
||||
:class="['lyric', $style.lyric, { [$style.draging]: isMsDown }, { [$style.lrcActiveZoom]: isZoomActiveLrc }]" :style="lrcStyles"
|
||||
@wheel="handleWheel" @mousedown="handleLyricMouseDown"
|
||||
@contextmenu.stop="handleShowLyricMenu"
|
||||
>
|
||||
<div :class="['pre', $style.lyricSpace]" />
|
||||
<div ref="dom_lyric_text" />
|
||||
<div :class="$style.lyricSpace" />
|
||||
</div>
|
||||
</transition>
|
||||
<transition enter-active-class="animated fadeIn" leave-active-class="animated fadeOut">
|
||||
<div v-if="isShowLyricProgressSetting" v-show="isStopScroll && !isShowLrcSelectContent" :class="$style.skip">
|
||||
<div ref="dom_skip_line" :class="$style.line" />
|
||||
<span :class="$style.label">{{ timeStr }}</span>
|
||||
<base-btn :class="$style.skipBtn" @mouseenter="handleSkipMouseEnter" @mouseleave="handleSkipMouseLeave" @click="handleSkipPlay">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="50%" viewBox="0 0 170 170" space="preserve">
|
||||
<use xlink:href="#icon-play" />
|
||||
</svg>
|
||||
</base-btn>
|
||||
</div>
|
||||
</transition>
|
||||
<transition enter-active-class="animated fadeIn" leave-active-class="animated fadeOut">
|
||||
<div v-if="isShowLrcSelectContent" :class="[$style.lyricSelectContent, 'select', 'scroll', 'lyricSelectContent']" @contextmenu="handleCopySelectText">
|
||||
<div v-for="(info, index) in lyric.lines" :key="index" :class="[$style.lyricSelectline, { [$style.lrcActive]: lyric.line == index }]">
|
||||
<span>{{ info.text }}</span>
|
||||
<template v-for="(lrc, i) in info.extendedLyrics" :key="i">
|
||||
<br>
|
||||
<span :class="$style.lyricSelectlineExtended">{{ lrc }}</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<LyricMenu v-model="lyricMenuVisible" :xy="lyricMenuXY" :lyric-info="lyricInfo" @update-lyric="handleUpdateLyric" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { clipboardWriteText } from '@common/utils/electron'
|
||||
import { lyric } from '@renderer/store/player/lyric'
|
||||
import { playProgress } from '@renderer/store/player/playProgress'
|
||||
import { isFullscreen } from '@renderer/store'
|
||||
import {
|
||||
isPlay,
|
||||
isShowLrcSelectContent,
|
||||
isShowPlayComment,
|
||||
musicInfo as playerMusicInfo,
|
||||
playMusicInfo,
|
||||
} from '@renderer/store/player/state'
|
||||
import {
|
||||
setMusicInfo,
|
||||
} from '@renderer/store/player/action'
|
||||
import { onMounted, onBeforeUnmount, computed, reactive, ref, nextTick, watch } from '@common/utils/vueTools'
|
||||
import useLyric from '@renderer/utils/compositions/useLyric'
|
||||
import LyricMenu from './components/LyricMenu'
|
||||
import { appSetting } from '@renderer/store/setting'
|
||||
import { setLyricOffset } from '@renderer/core/lyric'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
LyricMenu,
|
||||
},
|
||||
setup() {
|
||||
const isZoomActiveLrc = computed(() => appSetting['playDetail.isZoomActiveLrc'])
|
||||
const isShowLyricProgressSetting = computed(() => appSetting['playDetail.isShowLyricProgressSetting'])
|
||||
|
||||
const {
|
||||
dom_lyric,
|
||||
dom_lyric_text,
|
||||
dom_skip_line,
|
||||
isMsDown,
|
||||
isStopScroll,
|
||||
timeStr,
|
||||
handleLyricMouseDown,
|
||||
handleWheel,
|
||||
handleSkipPlay,
|
||||
handleSkipMouseEnter,
|
||||
handleSkipMouseLeave,
|
||||
handleScrollLrc,
|
||||
} = useLyric({ isPlay, lyric, playProgress, isShowLyricProgressSetting })
|
||||
|
||||
watch([isFullscreen, isShowPlayComment], () => {
|
||||
setTimeout(handleScrollLrc, 400)
|
||||
})
|
||||
|
||||
const lyricMenuVisible = ref(false)
|
||||
const lyricMenuXY = reactive({
|
||||
x: 0,
|
||||
y: 0,
|
||||
})
|
||||
const lyricInfo = reactive({
|
||||
lyric: '',
|
||||
tlyric: '',
|
||||
rlyric: '',
|
||||
lxlyric: '',
|
||||
rawlyric: '',
|
||||
musicInfo: null,
|
||||
})
|
||||
const updateMusicInfo = () => {
|
||||
lyricInfo.lyric = playerMusicInfo.lrc
|
||||
lyricInfo.tlyric = playerMusicInfo.tlrc
|
||||
lyricInfo.rlyric = playerMusicInfo.rlrc
|
||||
lyricInfo.lxlyric = playerMusicInfo.lxlrc
|
||||
lyricInfo.rawlyric = playerMusicInfo.rawlrc
|
||||
lyricInfo.musicInfo = playMusicInfo.musicInfo
|
||||
}
|
||||
const handleShowLyricMenu = event => {
|
||||
updateMusicInfo()
|
||||
lyricMenuXY.x = event.pageX
|
||||
lyricMenuXY.y = event.pageY
|
||||
if (lyricMenuVisible.value) return
|
||||
nextTick(() => {
|
||||
lyricMenuVisible.value = true
|
||||
})
|
||||
}
|
||||
const handleUpdateLyric = ({ lyric, tlyric, rlyric, lxlyric, offset }) => {
|
||||
setMusicInfo({
|
||||
lrc: lyric,
|
||||
tlrc: tlyric,
|
||||
rlrc: rlyric,
|
||||
lxlrc: lxlyric,
|
||||
})
|
||||
console.log(offset)
|
||||
setLyricOffset(offset)
|
||||
}
|
||||
|
||||
const lrcStyles = computed(() => {
|
||||
return {
|
||||
textAlign: appSetting['playDetail.style.align'],
|
||||
}
|
||||
})
|
||||
const lrcFontSize = computed(() => {
|
||||
let size = appSetting['playDetail.style.fontSize'] / 100
|
||||
if (isFullscreen.value) size = size *= 1.4
|
||||
return {
|
||||
'--playDetail-lrc-font-size': (isShowPlayComment.value ? size * 0.82 : size) + 'rem',
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
window.app_event.on('lyricUpdated', updateMusicInfo)
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
window.app_event.off('lyricUpdated', updateMusicInfo)
|
||||
})
|
||||
|
||||
return {
|
||||
dom_lyric,
|
||||
dom_lyric_text,
|
||||
dom_skip_line,
|
||||
isMsDown,
|
||||
timeStr,
|
||||
handleLyricMouseDown,
|
||||
handleWheel,
|
||||
handleSkipPlay,
|
||||
handleSkipMouseEnter,
|
||||
handleSkipMouseLeave,
|
||||
lyric,
|
||||
lrcStyles,
|
||||
lrcFontSize,
|
||||
isShowLrcSelectContent,
|
||||
isShowLyricProgressSetting,
|
||||
isZoomActiveLrc,
|
||||
isStopScroll,
|
||||
lyricMenuVisible,
|
||||
lyricMenuXY,
|
||||
handleShowLyricMenu,
|
||||
handleUpdateLyric,
|
||||
lyricInfo,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleCopySelectText() {
|
||||
let str = window.getSelection().toString()
|
||||
str = str.trim()
|
||||
if (!str.length) return
|
||||
clipboardWriteText(str)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="less" module>
|
||||
@import '@renderer/assets/styles/layout.less';
|
||||
|
||||
.right {
|
||||
flex: 0 0 60%;
|
||||
// padding: 0 30px;
|
||||
position: relative;
|
||||
transition: flex-basis @transition-normal;
|
||||
}
|
||||
.lyric {
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
font-size: var(--playDetail-lrc-font-size, 16px);
|
||||
-webkit-mask-image: linear-gradient(transparent 0%, #fff 20%, #fff 80%, transparent 100%);
|
||||
cursor: grab;
|
||||
&.draging {
|
||||
cursor: grabbing;
|
||||
}
|
||||
:global {
|
||||
.font-lrc {
|
||||
color: var(--color-200);
|
||||
}
|
||||
.line-content {
|
||||
line-height: 1.2;
|
||||
padding: calc(var(--playDetail-lrc-font-size, 16px) / 2) 1px;
|
||||
overflow-wrap: break-word;
|
||||
color: var(--color-200);
|
||||
transition: @transition-normal;
|
||||
transition-property: padding;
|
||||
|
||||
.extended {
|
||||
font-size: 0.8em;
|
||||
margin-top: 5px;
|
||||
}
|
||||
&.line-mode {
|
||||
.font-lrc {
|
||||
transition: @transition-fast;
|
||||
transition-property: font-size, color;
|
||||
}
|
||||
}
|
||||
&.line-mode.active .font-lrc, &.font-mode.played .font-lrc {
|
||||
color: var(--color-primary-dark-200);
|
||||
}
|
||||
&.font-mode .extended .font-lrc {
|
||||
transition: @transition-slow;
|
||||
transition-property: font-size, color;
|
||||
}
|
||||
|
||||
&.font-mode > .line > .font-lrc {
|
||||
> span {
|
||||
transition: @transition-normal;
|
||||
transition-property: font-size;
|
||||
font-size: 1em;
|
||||
background-repeat: no-repeat;
|
||||
background-color: var(--color-200);
|
||||
background-image: -webkit-linear-gradient(top, var(--color-primary-dark-200), var(--color-primary-dark-200));
|
||||
-webkit-text-fill-color: transparent;
|
||||
-webkit-background-clip: text;
|
||||
background-size: 0 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// p {
|
||||
// padding: 8px 0;
|
||||
// line-height: 1.2;
|
||||
// overflow-wrap: break-word;
|
||||
// transition: @transition-normal !important;
|
||||
// transition-property: color, font-size;
|
||||
// }
|
||||
// .lrc-active {
|
||||
// color: var(--color-primary);
|
||||
// font-size: 1.2em;
|
||||
// }
|
||||
}
|
||||
.lrc-active-zoom {
|
||||
:global {
|
||||
.line-content {
|
||||
&.active {
|
||||
.extended {
|
||||
font-size: .94em;
|
||||
}
|
||||
.line {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.skip {
|
||||
position: absolute;
|
||||
top: calc(38% + var(--playDetail-lrc-font-size, 16px) + 4px);
|
||||
left: 0;
|
||||
// height: 6px;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
// opacity: .5;
|
||||
.line {
|
||||
border-top: 2px dotted var(--color-primary-dark-100);
|
||||
opacity: .15;
|
||||
margin-right: 30px;
|
||||
-webkit-mask-image: linear-gradient(90deg, transparent 0%, transparent 15%, #fff 100%);
|
||||
}
|
||||
.label {
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
top: -14px;
|
||||
line-height: 1;
|
||||
font-size: 12px;
|
||||
color: var(--color-primary-dark-100);
|
||||
opacity: .7;
|
||||
}
|
||||
.skipBtn {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transform: translateY(-50%);
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: none !important;
|
||||
pointer-events: initial;
|
||||
transition: @transition-normal;
|
||||
transition-property: opacity;
|
||||
opacity: .8;
|
||||
&:hover {
|
||||
opacity: .6;
|
||||
}
|
||||
}
|
||||
}
|
||||
.lyricSelectContent {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
// text-align: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
z-index: 10;
|
||||
color: var(--color-400);
|
||||
|
||||
.lyricSelectline {
|
||||
padding: 8px 0;
|
||||
overflow-wrap: break-word;
|
||||
transition: @transition-normal !important;
|
||||
transition-property: color, font-size;
|
||||
line-height: 1.3;
|
||||
}
|
||||
.lyricSelectlineExtended {
|
||||
font-size: 14px;
|
||||
}
|
||||
.lrc-active {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.lyric-space {
|
||||
height: 70%;
|
||||
}
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user