优化侧栏图标显示,修复图标可能被裁切的问题(#1960)

pull/2077/head
lyswhut 2024-06-26 19:21:55 +08:00
parent 19f81cf379
commit 0acc9a553e
3 changed files with 81 additions and 28 deletions

View File

@ -2,6 +2,10 @@
- 新增 是否将歌词显示在状态栏 设置,默认关闭,该功能只在 MacOS 下可用(#1940 - 新增 是否将歌词显示在状态栏 设置,默认关闭,该功能只在 MacOS 下可用(#1940
### 优化
- 优化侧栏图标显示,修复图标可能被裁切的问题(#1960
### 修复 ### 修复
- 修复 MacOS 下点击 dock 右键菜单的退出按钮时,程序没有退出的问题(#1923 - 修复 MacOS 下点击 dock 右键菜单的退出按钮时,程序没有退出的问题(#1923

View File

@ -1,82 +1,94 @@
<template> <template>
<div :class="$style.menu"> <div ref="dom_menu" :class="$style.menu">
<ul :class="$style.list" role="toolbar"> <ul :class="$style.list" role="toolbar">
<li v-for="item in menus" :key="item.to" :class="$style.navItem" role="presentation"> <li v-for="item in menus" :key="item.to" :class="$style.navItem" role="presentation">
<router-link :class="[$style.link, {[$style.active]: $route.meta.name == item.name}]" role="tab" :aria-selected="$route.meta.name == item.name" :to="item.to" :aria-label="item.tips"> <router-link :class="[$style.link, {[$style.active]: $route.meta.name == item.name}]" role="tab" :aria-selected="$route.meta.name == item.name" :to="item.to" :aria-label="item.tips">
<div :class="$style.icon"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" :viewBox="item.iconSize" :height="item.size" :width="item.size" space="preserve">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" :viewBox="item.iconSize" space="preserve"> <use :xlink:href="item.icon" />
<use :xlink:href="item.icon" /> </svg>
</svg>
</div>
</router-link> </router-link>
</li> </li>
</ul> </ul>
</div> </div>
</template> </template>
<script> <script lang="ts">
import { appSetting } from '@renderer/store/setting' import { appSetting } from '@renderer/store/setting'
import { useI18n } from '@root/lang'
import { ref, computed } from '@common/utils/vueTools'
import { useIconSize } from '@renderer/utils/compositions/useIconSize'
export default { export default {
name: 'NavBar', name: 'NavBar',
setup() { setup() {
return { const t = useI18n()
appSetting, const dom_menu = ref<HTMLElement>()
} const iconSize = useIconSize(dom_menu, 0.32)
},
computed: { const menus = computed(() => {
menus() { const size = iconSize.value
return [ return [
{ {
to: '/search', to: '/search',
tips: this.$t('search'), tips: t('search'),
icon: '#icon-search-2', icon: '#icon-search-2',
iconSize: '0 0 425.2 425.2', iconSize: '0 0 425.2 425.2',
size,
name: 'Search', name: 'Search',
enable: true, enable: true,
}, },
{ {
to: '/songList/list', to: '/songList/list',
tips: this.$t('song_list'), tips: t('song_list'),
icon: '#icon-album', icon: '#icon-album',
iconSize: '0 0 425.2 425.2', iconSize: '0 0 425.2 425.2',
size,
name: 'SongList', name: 'SongList',
enable: true, enable: true,
}, },
{ {
to: '/leaderboard', to: '/leaderboard',
tips: this.$t('leaderboard'), tips: t('leaderboard'),
icon: '#icon-leaderboard', icon: '#icon-leaderboard',
iconSize: '0 0 425.22 425.2', iconSize: '0 0 425.22 425.2',
size,
name: 'Leaderboard', name: 'Leaderboard',
enable: true, enable: true,
}, },
{ {
to: '/list', to: '/list',
tips: this.$t('my_list'), tips: t('my_list'),
icon: '#icon-love', icon: '#icon-love',
iconSize: '0 0 444.87 391.18', iconSize: '0 0 444.87 391.18',
size,
name: 'List', name: 'List',
enable: true, enable: true,
}, },
{ {
to: '/download', to: '/download',
tips: this.$t('download'), tips: t('download'),
icon: '#icon-download-2', icon: '#icon-download-2',
iconSize: '0 0 425.2 425.2', iconSize: '0 0 425.2 425.2',
enable: this.appSetting['download.enable'], size,
enable: appSetting['download.enable'],
name: 'Download', name: 'Download',
}, },
{ {
to: '/setting', to: '/setting',
tips: this.$t('setting'), tips: t('setting'),
icon: '#icon-setting', icon: '#icon-setting',
iconSize: '0 0 493.23 436.47', iconSize: '0 0 493.23 436.47',
size,
enable: true, enable: true,
name: 'Setting', name: 'Setting',
}, },
].filter(m => m.enable) ].filter(m => m.enable)
}, })
return {
appSetting,
menus,
dom_menu,
}
}, },
} }
</script> </script>
@ -141,7 +153,7 @@ export default {
transition-property: background-color, opacity; transition-property: background-color, opacity;
color: var(--color-nav-font); color: var(--color-nav-font);
cursor: pointer; cursor: pointer;
font-size: 11.5px; // font-size: 11.5px;
text-align: center; text-align: center;
outline: none; outline: none;
display: flex; display: flex;
@ -190,11 +202,11 @@ export default {
} }
} }
.icon { // .icon {
// margin-bottom: 5px; // // margin-bottom: 5px;
&> svg { // &> svg {
width: 32%; // width: 32%;
} // }
} // }
</style> </style>

View File

@ -0,0 +1,37 @@
import { type Ref, onBeforeUnmount, onMounted, ref } from '@common/utils/vueTools'
const onDomSizeChanged = (dom: HTMLElement, onChanged: (width: number, height: number) => void) => {
// 使用 ResizeObserver 监听大小变化
const resizeObserver = new ResizeObserver(entries => {
for (let entry of entries) {
const { width, height } = entry.contentRect
// console.log(dom.offsetLeft, dom.offsetTop, left, top, width, height)
onChanged(Math.trunc(width), Math.trunc(height))
}
})
resizeObserver.observe(dom)
onChanged(dom.clientWidth, dom.clientHeight)
return () => {
resizeObserver.disconnect()
}
}
export const useIconSize = (parentDom: Ref<HTMLElement | undefined>, size: number) => {
const iconSize = ref('32px')
let unsub: (() => void) | null = null
onMounted(() => {
if (!parentDom.value) return
unsub = onDomSizeChanged(parentDom.value, (width, height) => {
iconSize.value = Math.trunc(width * size) + 'px'
})
})
onBeforeUnmount(() => {
unsub?.()
})
return iconSize
}