mirror of
https://github.com/ayangweb/BongoCat.git
synced 2026-03-12 17:51:48 +08:00
refactor: 优化模型尺寸的处理逻辑 (#552)
This commit is contained in:
@@ -1,37 +1,34 @@
|
||||
import { convertFileSrc } from '@tauri-apps/api/core'
|
||||
import { LogicalSize, PhysicalSize } from '@tauri-apps/api/dpi'
|
||||
import { resolveResource } from '@tauri-apps/api/path'
|
||||
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { isNil, round } from 'es-toolkit'
|
||||
import { computed, watch } from 'vue'
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
import live2d from '../utils/live2d'
|
||||
import { getCursorMonitor } from '../utils/monitor'
|
||||
|
||||
import { useCatStore } from '@/stores/cat'
|
||||
import { useModelStore } from '@/stores/model'
|
||||
import { getImageSize } from '@/utils/dom'
|
||||
import { join } from '@/utils/path'
|
||||
|
||||
const appWindow = getCurrentWebviewWindow()
|
||||
|
||||
interface ModelSize {
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
export function useModel() {
|
||||
const modelStore = useModelStore()
|
||||
const catStore = useCatStore()
|
||||
|
||||
const backgroundImage = computed(() => {
|
||||
if (!modelStore.currentModel) return
|
||||
|
||||
return convertFileSrc(join(modelStore.currentModel.path, 'resources', 'background.png'))
|
||||
})
|
||||
const modelSize = ref<ModelSize>()
|
||||
|
||||
watch(() => modelStore.currentModel, handleLoad, { deep: true, immediate: true })
|
||||
|
||||
watch([() => catStore.scale, backgroundImage], async () => {
|
||||
if (!backgroundImage.value) return
|
||||
watch([() => catStore.scale, modelSize], async () => {
|
||||
if (!modelSize.value) return
|
||||
|
||||
const { width, height } = await getImageSize(backgroundImage.value)
|
||||
const { width, height } = modelSize.value
|
||||
|
||||
appWindow.setSize(
|
||||
new PhysicalSize({
|
||||
@@ -49,11 +46,13 @@ export function useModel() {
|
||||
|
||||
await resolveResource(path)
|
||||
|
||||
const data = await live2d.load(path)
|
||||
const { width, height, ...rest } = await live2d.load(path)
|
||||
|
||||
modelSize.value = { width, height }
|
||||
|
||||
handleResize()
|
||||
|
||||
Object.assign(modelStore, data)
|
||||
Object.assign(modelStore, rest)
|
||||
} catch (error) {
|
||||
message.error(String(error))
|
||||
}
|
||||
@@ -64,11 +63,11 @@ export function useModel() {
|
||||
}
|
||||
|
||||
async function handleResize() {
|
||||
if (!backgroundImage.value) return
|
||||
if (!modelSize.value) return
|
||||
|
||||
live2d.fitModel()
|
||||
|
||||
const { width, height } = await getImageSize(backgroundImage.value)
|
||||
const { width, height } = modelSize.value
|
||||
|
||||
if (round(innerWidth / innerHeight, 1) !== round(width / height, 1)) {
|
||||
await appWindow.setSize(
|
||||
@@ -134,7 +133,6 @@ export function useModel() {
|
||||
}
|
||||
|
||||
return {
|
||||
backgroundImage,
|
||||
handleLoad,
|
||||
handleDestroy,
|
||||
handleResize,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { convertFileSrc, invoke } from '@tauri-apps/api/core'
|
||||
import { Menu } from '@tauri-apps/api/menu'
|
||||
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'
|
||||
import { exists } from '@tauri-apps/plugin-fs'
|
||||
import { useDebounceFn, useEventListener } from '@vueuse/core'
|
||||
import { onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
|
||||
@@ -16,11 +17,12 @@ import { join } from '@/utils/path'
|
||||
|
||||
const appWindow = getCurrentWebviewWindow()
|
||||
const { pressedMouses, mousePosition, pressedLeftKeys, pressedRightKeys } = useDevice()
|
||||
const { backgroundImage, handleDestroy, handleResize, handleMouseDown, handleMouseMove, handleKeyDown } = useModel()
|
||||
const { handleDestroy, handleResize, handleMouseDown, handleMouseMove, handleKeyDown } = useModel()
|
||||
const catStore = useCatStore()
|
||||
const { getSharedMenu } = useSharedMenu()
|
||||
const modelStore = useModelStore()
|
||||
const resizing = ref(false)
|
||||
const backgroundImagePath = ref<string>()
|
||||
|
||||
onMounted(() => {
|
||||
invoke(INVOKE_KEY.START_DEVICE_LISTENING)
|
||||
@@ -62,6 +64,16 @@ watch(() => catStore.penetrable, (value) => {
|
||||
|
||||
watch(() => catStore.alwaysOnTop, setAlwaysOnTop, { immediate: true })
|
||||
|
||||
watch(() => modelStore.currentModel, async (model) => {
|
||||
if (!model) return
|
||||
|
||||
const path = join(model.path, 'resources', 'background.png')
|
||||
|
||||
const existed = await exists(path)
|
||||
|
||||
backgroundImagePath.value = existed ? convertFileSrc(path) : void 0
|
||||
}, { deep: true, immediate: true })
|
||||
|
||||
function handleWindowDrag() {
|
||||
appWindow.startDragging()
|
||||
}
|
||||
@@ -76,7 +88,7 @@ async function handleContextmenu(event: MouseEvent) {
|
||||
menu.popup()
|
||||
}
|
||||
|
||||
function resolveImagePath(key: string, side: 'left' | 'right' = 'left') {
|
||||
function resolveKeyImagePath(key: string, side: 'left' | 'right' = 'left') {
|
||||
return convertFileSrc(join(modelStore.currentModel!.path, 'resources', `${side}-keys`, `${key}.png`))
|
||||
}
|
||||
</script>
|
||||
@@ -89,22 +101,23 @@ function resolveImagePath(key: string, side: 'left' | 'right' = 'left') {
|
||||
@contextmenu="handleContextmenu"
|
||||
@mousedown="handleWindowDrag"
|
||||
>
|
||||
<img :src="backgroundImage">
|
||||
<img
|
||||
v-if="backgroundImagePath"
|
||||
:src="backgroundImagePath"
|
||||
>
|
||||
|
||||
<canvas id="live2dCanvas" />
|
||||
|
||||
<img
|
||||
v-for="key in pressedLeftKeys"
|
||||
:key="key"
|
||||
class="object-contain"
|
||||
:src="resolveImagePath(key)"
|
||||
:src="resolveKeyImagePath(key)"
|
||||
>
|
||||
|
||||
<img
|
||||
v-for="key in pressedRightKeys"
|
||||
:key="key"
|
||||
class="object-contain"
|
||||
:src="resolveImagePath(key, 'right')"
|
||||
:src="resolveKeyImagePath(key, 'right')"
|
||||
>
|
||||
|
||||
<div
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
export function getImageSize(src: string) {
|
||||
return new Promise<{ width: number, height: number }>((resolve, reject) => {
|
||||
const img = new Image()
|
||||
|
||||
img.src = src
|
||||
|
||||
img.onload = () => {
|
||||
const { naturalWidth, naturalHeight } = img
|
||||
|
||||
resolve({ width: naturalWidth, height: naturalHeight })
|
||||
}
|
||||
|
||||
img.onerror = reject
|
||||
})
|
||||
}
|
||||
@@ -67,6 +67,8 @@ class Live2d {
|
||||
const { motions, expressions } = modelSettings
|
||||
|
||||
return {
|
||||
width,
|
||||
height,
|
||||
motions,
|
||||
expressions,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user