优化窗口控制按钮聚焦效果显示时机

pull/1761/head
lyswhut 2023-12-05 13:06:48 +08:00
parent cac2d0e050
commit 15942a7b96
5 changed files with 389 additions and 154 deletions

View File

@ -1,11 +1,11 @@
<template>
<div v-show="!isFullscreen" :class="$style.controlBtn">
<button type="button" :class="[$style.btn, $style.close]" :aria-label="$t('close')" @click="closeWindow">
<div v-show="!isFullscreen" ref="dom_btns" :class="$style.controlBtn">
<button type="button" :class="[$style.btn, $style.close]" :aria-label="$t('close')" ignore-tip :title="$t('close')" @click="closeWindow">
<svg :class="$style.controlBtniIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="100%" viewBox="0 0 24 24" space="preserve">
<use xlink:href="#icon-window-close" />
</svg>
</button>
<button type="button" :class="[$style.btn, $style.min]" :aria-label="$t('min')" @click="minWindow">
<button type="button" :class="[$style.btn, $style.min]" :aria-label="$t('min')" ignore-tip :title="$t('min')" @click="minWindow">
<svg :class="$style.controlBtniIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="100%" viewBox="0 0 24 24" space="preserve">
<use xlink:href="#icon-window-minimize" />
</svg>
@ -15,9 +15,37 @@
<script setup>
import { minWindow, closeWindow } from '@renderer/utils/ipc'
import { onMounted, onBeforeUnmount, ref, useCssModule } from '@common/utils/vueTools'
// import { getRandom } from '../../utils'
import { isFullscreen } from '@renderer/store'
const dom_btns = ref()
const cssModule = useCssModule()
const handle_focus = () => {
if (!dom_btns.value) return
dom_btns.value.classList.remove(cssModule.hover)
}
const handle_mouseenter = () => {
dom_btns.value.classList.add(cssModule.hover)
}
const handle_mouseleave = () => {
dom_btns.value.classList.remove(cssModule.hover)
}
onMounted(() => {
window.app_event.on('focus', handle_focus)
dom_btns.value.addEventListener('mouseenter', handle_mouseenter)
dom_btns.value.addEventListener('mouseleave', handle_mouseleave)
})
onBeforeUnmount(() => {
window.app_event.off('focus', handle_focus)
dom_btns.value.removeEventListener('mouseenter', handle_mouseenter)
dom_btns.value.removeEventListener('mouseleave', handle_mouseleave)
})
</script>
<style lang="less" module>
@ -36,7 +64,7 @@ import { isFullscreen } from '@renderer/store'
-webkit-app-region: no-drag;
opacity: .5;
transition: opacity @transition-normal;
&:hover {
&.hover {
opacity: .8;
.controlBtniIcon {
opacity: 1;

View File

@ -0,0 +1,163 @@
<template lang="pug">
div(:class="$style.header")
div(ref="dom_btns" :class="$style.controBtn")
button(type="button" :class="$style.hide" :aria-label="$t('player__hide_detail_tip')" ignore-tip :title="$t('player__hide_detail_tip')" @click="hide")
svg(:class="$style.controBtnIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="80%" viewBox="0 0 30.727 30.727" space="preserve")
use(xlink:href="#icon-window-hide")
button(type="button" :class="$style.fullscreenExit" :aria-label="$t('fullscreen_exit')" ignore-tip :title="$t('fullscreen_exit')" @click="fullscreenExit")
svg(:class="$style.controBtnIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="100%")
use(xlink:href="#icon-fullscreen-exit")
button(type="button" :class="$style.min" :aria-label="$t('min')" ignore-tip :title="$t('min')" @click="minWindow")
svg(:class="$style.controBtnIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="100%" viewBox="0 0 24 24" space="preserve")
use(xlink:href="#icon-window-minimize")
//- button(type="button" :class="$style.max" @click="max")
button(type="button" :class="$style.close" :aria-label="$t('close')" ignore-tip :title="$t('close')" @click="closeWindow")
svg(:class="$style.controBtnIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="100%" viewBox="0 0 24 24" space="preserve")
use(xlink:href="#icon-window-close")
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, useCssModule } from '@common/utils/vueTools'
import { isFullscreen } from '@renderer/store'
import { setShowPlayerDetail } from '@renderer/store/player/action'
import { closeWindow, minWindow, setFullScreen } from '@renderer/utils/ipc'
const dom_btns = ref()
const cssModule = useCssModule()
const handle_focus = () => {
if (!dom_btns.value) return
dom_btns.value.classList.remove(cssModule.hover)
}
const handle_mouseenter = () => {
dom_btns.value.classList.add(cssModule.hover)
}
const handle_mouseleave = () => {
dom_btns.value.classList.remove(cssModule.hover)
}
onMounted(() => {
window.app_event.on('focus', handle_focus)
dom_btns.value.addEventListener('mouseenter', handle_mouseenter)
dom_btns.value.addEventListener('mouseleave', handle_mouseleave)
})
onBeforeUnmount(() => {
window.app_event.off('focus', handle_focus)
dom_btns.value.removeEventListener('mouseenter', handle_mouseenter)
dom_btns.value.removeEventListener('mouseleave', handle_mouseleave)
})
const hide = () => {
dom_btns.value?.classList.remove(cssModule.hover)
setShowPlayerDetail(false)
}
const fullscreenExit = () => {
dom_btns.value?.classList.remove(cssModule.hover)
void setFullScreen(false).then((fullscreen) => {
isFullscreen.value = fullscreen
})
}
</script>
<style lang="less" module>
@import '@renderer/assets/styles/layout.less';
@control-btn-width: @height-toolbar * .26;
:global(.fullscreen) {
.header {
-webkit-app-region: no-drag;
align-self: flex-start;
.controBtn {
.close, .min {
display: none;
}
.fullscreenExit {
display: flex;
}
}
}
}
.header {
position: relative;
flex: 0 0 @height-toolbar;
-webkit-app-region: drag;
width: 100%;
.controBtn {
position: absolute;
top: 0;
display: flex;
-webkit-app-region: no-drag;
button {
display: flex;
position: relative;
background: none;
border: none;
outline: none;
padding: 1px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
}
.fullscreenExit {
display: none;
}
}
.controBtn {
align-items: center;
padding: 0 @control-btn-width;
left: 0;
flex-direction: row-reverse;
height: @height-toolbar * .7;
transition: opacity @transition-normal;
opacity: .5;
&.hover {
opacity: .8;
.controBtnIcon {
opacity: 1;
}
}
button {
width: @control-btn-width;
height: @control-btn-width;
border-radius: 50%;
color: var(--color-font);
+ button {
margin-right: (@control-btn-width / 2);
}
&.hide {
background-color: var(--color-btn-hide);
}
&.min, &.fullscreenExit {
background-color: var(--color-btn-min);
}
// &.max {
// background-color: var(--color-btn-max);
// }
&.close {
background-color: var(--color-btn-close);
}
}
}
.controBtnIcon {
opacity: 0;
transition: opacity 0.2s ease-in-out;
}
}
</style>

View File

@ -0,0 +1,146 @@
<template lang="pug">
div(:class="$style.header")
div(ref="dom_btns" :class="$style.controBtn")
button(ref="dom_hide_btn" type="button" :class="$style.hide" :aria-label="$t('player__hide_detail_tip')" ignore-tip :title="$t('player__hide_detail_tip')" @click="hide")
svg(:class="$style.controBtnIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="35%" viewBox="0 0 30.727 30.727" space="preserve")
use(xlink:href="#icon-window-hide")
button(ref="dom_fullscreen_btn" type="button" :class="$style.fullscreenExit" :aria-label="$t('fullscreen_exit')" ignore-tip :title="$t('fullscreen_exit')" @click="fullscreenExit")
svg(:class="$style.controBtnIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="60%")
use(xlink:href="#icon-fullscreen-exit")
button(type="button" :class="$style.min" :aria-label="$t('min')" ignore-tip :title="$t('min')" @click="minWindow")
svg(:class="$style.controBtnIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="60%" viewBox="0 0 24 24" space="preserve")
use(xlink:href="#icon-window-minimize-2")
//- button(type="button" :class="$style.max" @click="max")
button(type="button" :class="$style.close" :aria-label="$t('close')" ignore-tip :title="$t('close')" @click="closeWindow")
svg(:class="$style.controBtnIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="60%" viewBox="0 0 24 24" space="preserve")
use(xlink:href="#icon-window-close-2")
</template>
<script setup>
import { onMounted, onBeforeUnmount, ref, useCssModule } from '@common/utils/vueTools'
import { isFullscreen } from '@renderer/store'
import { setShowPlayerDetail } from '@renderer/store/player/action'
import { closeWindow, minWindow, setFullScreen } from '@renderer/utils/ipc'
const dom_btns = ref()
const cssModule = useCssModule()
const handle_focus = () => {
if (!dom_btns.value) return
for (const node of dom_btns.value.childNodes) {
if (node.tagName != 'BUTTON') continue
node.classList.remove(cssModule.hover)
}
}
const getBtnEl = (el) => el.tagName == 'BUTTON' || !el ? el : getBtnEl(el.parentNode)
const handle_mouseover = (event) => {
const btn = getBtnEl(event.target)
if (!btn) return
btn.classList.add(cssModule.hover)
}
const handle_mouseout = (event) => {
const btn = getBtnEl(event.target)
if (!btn) return
btn.classList.remove(cssModule.hover)
}
onMounted(() => {
window.app_event.on('focus', handle_focus)
dom_btns.value.addEventListener('mouseover', handle_mouseover)
dom_btns.value.addEventListener('mouseout', handle_mouseout)
})
onBeforeUnmount(() => {
window.app_event.off('focus', handle_focus)
dom_btns.value.removeEventListener('mouseover', handle_mouseover)
dom_btns.value.removeEventListener('mouseout', handle_mouseout)
})
const dom_hide_btn = ref()
const hide = () => {
dom_hide_btn.value?.classList.remove(cssModule.hover)
setShowPlayerDetail(false)
}
const dom_fullscreen_btn = ref()
const fullscreenExit = () => {
dom_fullscreen_btn.value?.classList.remove(cssModule.hover)
void setFullScreen(false).then((fullscreen) => {
isFullscreen.value = fullscreen
})
}
</script>
<style lang="less" module>
@import '@renderer/assets/styles/layout.less';
@control-btn-width: @height-toolbar * .26;
:global(.fullscreen) {
.header {
-webkit-app-region: no-drag;
align-self: flex-start;
.controBtn {
.close, .min {
display: none;
}
.fullscreenExit {
display: flex;
}
}
}
}
.header {
position: relative;
flex: 0 0 @height-toolbar;
-webkit-app-region: drag;
width: 100%;
align-self: flex-start;
.controBtn {
position: absolute;
top: 0;
display: flex;
-webkit-app-region: no-drag;
button {
display: flex;
position: relative;
background: none;
border: none;
outline: none;
padding: 1px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
}
.fullscreenExit {
display: none;
}
}
.controBtn {
right: 0;
button {
width: 46px;
height: 30px;
color: var(--color-font-label);
transition: background-color 0.2s ease-in-out;
&.hover {
background-color: var(--color-button-background-hover);
&.close {
background-color: var(--color-btn-close);
}
}
}
}
}
</style>

View File

@ -1,41 +1,11 @@
<template lang="pug">
transition(enter-active-class="animated slideInRight" leave-active-class="animated slideOutDown" @after-enter="handleAfterEnter" @after-leave="handleAfterLeave")
div(v-if="isShowPlayerDetail" :class="[$style.container, { [$style.fullscreen]: isFullscreen }]" @contextmenu="handleContextMenu")
div(v-if="isShowPlayerDetail" :class="[$style.container, { fullscreen: isFullscreen }]" @contextmenu="handleContextMenu")
div(:class="$style.bg")
//- div(:class="$style.bg" :style="bgStyle")
//- div(:class="$style.bg2")
div(v-if="appSetting['common.controlBtnPosition'] == 'left'" :class="[$style.header, $style.controlBtnLeft]")
div(:class="$style.controBtn")
button(type="button" :class="$style.hide" :aria-label="$t('player__hide_detail_tip')" @click="hide")
svg(:class="$style.controBtnIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="80%" viewBox="0 0 30.727 30.727" space="preserve")
use(xlink:href="#icon-window-hide")
button(type="button" :class="$style.fullscreenExit" :aria-label="$t('fullscreen_exit')" @click="fullscreenExit")
svg(:class="$style.controBtnIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="100%")
use(xlink:href="#icon-fullscreen-exit")
button(type="button" :class="$style.min" :aria-label="$t('min')" @click="min")
svg(:class="$style.controBtnIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="100%" viewBox="0 0 24 24" space="preserve")
use(xlink:href="#icon-window-minimize")
//- button(type="button" :class="$style.max" @click="max")
button(type="button" :class="$style.close" :aria-label="$t('close')" @click="close")
svg(:class="$style.controBtnIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="100%" viewBox="0 0 24 24" space="preserve")
use(xlink:href="#icon-window-close")
div(v-else :class="[$style.header, $style.controlBtnRight]")
div(:class="$style.controBtn")
button(type="button" :class="$style.hide" :aria-label="$t('player__hide_detail_tip')" @click="hide")
svg(:class="$style.controBtnIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="35%" viewBox="0 0 30.727 30.727" space="preserve")
use(xlink:href="#icon-window-hide")
button(type="button" :class="$style.fullscreenExit" :aria-label="$t('fullscreen_exit')" @click="fullscreenExit")
svg(:class="$style.controBtnIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="60%")
use(xlink:href="#icon-fullscreen-exit")
button(type="button" :class="$style.min" :aria-label="$t('min')" @click="min")
svg(:class="$style.controBtnIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="60%" viewBox="0 0 24 24" space="preserve")
use(xlink:href="#icon-window-minimize-2")
//- button(type="button" :class="$style.max" @click="max")
button(type="button" :class="$style.close" :aria-label="$t('close')" @click="close")
svg(:class="$style.controBtnIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="60%" viewBox="0 0 24 24" space="preserve")
use(xlink:href="#icon-window-close-2")
ControlBtnsLeftHeader(v-if="appSetting['common.controlBtnPosition'] == 'left'")
ControlBtnsRightHeader(v-else)
div(:class="[$style.main, {[$style.showComment]: isShowPlayComment}]")
div.left(:class="$style.left")
//- div(:class="$style.info")
@ -73,6 +43,8 @@ import {
import LyricPlayer from './LyricPlayer.vue'
import PlayBar from './PlayBar.vue'
import MusicComment from './components/MusicComment/index.vue'
import ControlBtnsLeftHeader from './ControlBtnsLeftHeader.vue'
import ControlBtnsRightHeader from './ControlBtnsRightHeader.vue'
import { registerAutoHideMounse, unregisterAutoHideMounse } from './autoHideMounse'
import { appSetting } from '@renderer/store/setting'
import { closeWindow, maxWindow, minWindow, setFullScreen } from '@renderer/utils/ipc'
@ -80,6 +52,8 @@ import { closeWindow, maxWindow, minWindow, setFullScreen } from '@renderer/util
export default {
name: 'CorePlayDetail',
components: {
ControlBtnsLeftHeader,
ControlBtnsRightHeader,
LyricPlayer,
PlayBar,
MusicComment,
@ -185,22 +159,6 @@ export default {
* {
box-sizing: border-box;
}
&.fullscreen {
.header {
-webkit-app-region: no-drag;
align-self: flex-start;
.controBtn {
.close, .min {
display: none;
}
.fullscreenExit {
display: flex;
}
}
}
}
}
.bg {
position: absolute;
@ -242,103 +200,6 @@ export default {
// background-color: rgba(255, 255, 255, .8);
// }
.header {
position: relative;
flex: 0 0 @height-toolbar;
-webkit-app-region: drag;
width: 100%;
.controBtn {
position: absolute;
top: 0;
display: flex;
-webkit-app-region: no-drag;
button {
display: flex;
position: relative;
background: none;
border: none;
outline: none;
padding: 1px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
}
.fullscreenExit {
display: none;
}
}
&.controlBtnLeft {
.controBtn {
align-items: center;
padding: 0 @control-btn-width;
left: 0;
flex-direction: row-reverse;
height: @height-toolbar * .7;
transition: opacity @transition-normal;
opacity: .5;
&:hover {
opacity: .8;
.controBtnIcon {
opacity: 1;
}
}
button {
width: @control-btn-width;
height: @control-btn-width;
border-radius: 50%;
color: var(--color-font);
+ button {
margin-right: (@control-btn-width / 2);
}
&.hide {
background-color: var(--color-btn-hide);
}
&.min, &.fullscreenExit {
background-color: var(--color-btn-min);
}
// &.max {
// background-color: var(--color-btn-max);
// }
&.close {
background-color: var(--color-btn-close);
}
}
}
.controBtnIcon {
opacity: 0;
transition: opacity 0.2s ease-in-out;
}
}
&.controlBtnRight {
align-self: flex-start;
.controBtn {
right: 0;
button {
width: 46px;
height: 30px;
color: var(--color-font-label);
transition: background-color 0.2s ease-in-out;
&:hover {
background-color: var(--color-button-background-hover);
&.close {
background-color: var(--color-btn-close);
}
}
}
}
}
}
.main {
flex: auto;
min-height: 0;

View File

@ -1,11 +1,11 @@
<template>
<div v-show="!isFullscreen" :class="$style.control">
<button type="button" :class="[$style.btn, $style.min]" :aria-label="$t('min')" @click="minWindow">
<div v-show="!isFullscreen" ref="dom_btns" :class="$style.control">
<button type="button" :class="[$style.btn, $style.min]" :aria-label="$t('min')" ignore-tip :title="$t('min')" @click="minWindow">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="60%" viewBox="0 0 24 24" space="preserve">
<use xlink:href="#icon-window-minimize-2" />
</svg>
</button>
<button type="button" :class="[$style.btn, $style.close]" :aria-label="$t('close')" @click="closeWindow">
<button type="button" :class="[$style.btn, $style.close]" :aria-label="$t('close')" ignore-tip :title="$t('close')" @click="closeWindow">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" height="60%" viewBox="0 0 24 24" space="preserve">
<use xlink:href="#icon-window-close-2" />
</svg>
@ -15,8 +15,45 @@
<script setup>
import { minWindow, closeWindow } from '@renderer/utils/ipc'
import { onMounted, onBeforeUnmount, ref, useCssModule } from '@common/utils/vueTools'
// import { getRandom } from '../../utils'
import { isFullscreen } from '@renderer/store'
const dom_btns = ref()
const cssModule = useCssModule()
const handle_focus = () => {
if (!dom_btns.value) return
for (const node of dom_btns.value.childNodes) {
if (node.tagName != 'BUTTON') continue
node.classList.remove(cssModule.hover)
}
}
const getBtnEl = (el) => el.tagName == 'BUTTON' || !el ? el : getBtnEl(el.parentNode)
const handle_mouseover = (event) => {
const btn = getBtnEl(event.target)
if (!btn) return
btn.classList.add(cssModule.hover)
}
const handle_mouseout = (event) => {
const btn = getBtnEl(event.target)
if (!btn) return
btn.classList.remove(cssModule.hover)
}
onMounted(() => {
window.app_event.on('focus', handle_focus)
dom_btns.value.addEventListener('mouseover', handle_mouseover)
dom_btns.value.addEventListener('mouseout', handle_mouseout)
})
onBeforeUnmount(() => {
window.app_event.off('focus', handle_focus)
dom_btns.value.removeEventListener('mouseover', handle_mouseover)
dom_btns.value.removeEventListener('mouseout', handle_mouseout)
})
</script>
@ -43,7 +80,7 @@ import { isFullscreen } from '@renderer/store'
cursor: pointer;
color: var(--color-font-label);
transition: background-color 0.2s ease-in-out;
&:hover {
&.hover {
&.min, &.max {
background-color: var(--color-button-background-hover);
}