轴点功能修复

This commit is contained in:
tianmo committed 2026-10-22 12:04:29 +08:00
1 parent 4d54c87681
commit 2b8fd067b3
16 files changed
+1750 -105

No files matched your search

+43 -8
View File
@@ -64,7 +64,7 @@
<div class="pivot-toggle-sub" :title="pivotSummary">{{ pivotSummary }}</div>
</div>
<label class="pivot-switch" :title="pivotOpen ? '收起轴点调整' : '展开轴点调整'">
<input v-model="pivotOpen" type="checkbox" />
<input v-model="pivotOpen" type="checkbox" @change="onPivotToggle" />
<span class="pivot-switch-ui"></span>
</label>
</div>
@@ -112,7 +112,7 @@
</template>
<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import NumSlider from './NumSlider.vue'
import PivotEditor from './PivotEditor.vue'
@@ -138,6 +138,8 @@ const props = withDefaults(defineProps<{
namePlaceholder?: string
showFolder?: boolean
supportsSequence?: boolean
/** 资源卡片的稳定标识(如“系统id:资源id”),用于记住轴点面板展开状态。 */
pivotKey?: string
}>(), {
namePlaceholder: 'particle',
showFolder: true,
@@ -169,17 +171,42 @@ const displayPreviewUrl = computed(() => props.resource.imageMode === 'sequence'
? props.resource.sequenceFrames?.[0]?.previewUrl || ''
: props.resource.previewUrl)
const pivotOpen = ref(false)
const pivotFullscreen = ref(false)
const draftX = ref(0.5)
const draftY = ref(0.5)
// 轴点面板展开状态属于 UI 状态:按资源独立记忆;用 sessionStorage 保证组件重挂载/HMR 后也不收起。
const PIVOT_UI_STORAGE_KEY = 'SpineParticle.PivotPanels.v1'
function loadPivotPanelState(): Record<string, boolean> {
try {
const parsed = JSON.parse(sessionStorage.getItem(PIVOT_UI_STORAGE_KEY) || '{}')
return parsed && typeof parsed === 'object' ? parsed as Record<string, boolean> : {}
} catch {
return {}
}
}
const pivotOpenState = loadPivotPanelState()
const resolvedPivotKey = computed(() => props.pivotKey || `particle-image:${props.resource.id}`)
const supportsPivot = computed(() => typeof props.resource.anchorX === 'number' && typeof props.resource.anchorY === 'number')
const pivotCentered = computed(() =>
Math.abs((props.resource.anchorX ?? 0.5) - 0.5) < 1e-4 && Math.abs((props.resource.anchorY ?? 0.5) - 0.5) < 1e-4,
)
// 有明确记忆就用记忆;没有记忆时,已自定义轴点的资源默认展开,避免“开关关闭但轴点生效”的错觉。
const hasStoredPivotOpen = typeof pivotOpenState[resolvedPivotKey.value] === 'boolean'
const pivotOpen = ref(hasStoredPivotOpen ? pivotOpenState[resolvedPivotKey.value] : !pivotCentered.value)
watch(pivotOpen, (open) => {
pivotOpenState[resolvedPivotKey.value] = open
try { sessionStorage.setItem(PIVOT_UI_STORAGE_KEY, JSON.stringify(pivotOpenState)) } catch { /* 隐私模式忽略 */ }
})
watch(resolvedPivotKey, (key) => {
pivotOpen.value = typeof pivotOpenState[key] === 'boolean' ? pivotOpenState[key] : !pivotCentered.value
})
// 轴点已自定义时开关必须为开启状态,避免出现“开关关闭但轴点仍生效”的不一致。
watch(() => pivotCentered.value, (centered) => {
if (!centered) pivotOpen.value = true
}, { immediate: true })
const pivotFullscreen = ref(false)
const draftX = ref(0.5)
const draftY = ref(0.5)
const pivotSummary = computed(() => {
const x = (Math.min(1, Math.max(0, props.resource.anchorX ?? 0.5)) * 100).toFixed(1)
const y = (Math.min(1, Math.max(0, props.resource.anchorY ?? 0.5)) * 100).toFixed(1)
const x = ((props.resource.anchorX ?? 0.5) * 100).toFixed(1)
const y = ((props.resource.anchorY ?? 0.5) * 100).toFixed(1)
if (pivotOpen.value) return `已开启:X ${x}% | Y ${y}%`
if (pivotCentered.value) return '未开启,默认围绕图片正中心 (50%, 50%)'
return `轴点已自定义:X ${x}% | Y ${y}%`
@@ -191,6 +218,14 @@ function openPivotFullscreen() {
pivotFullscreen.value = true
}
/** 关闭开关表示回到默认中心轴点;自定义轴点不允许处于“关闭”状态。 */
function onPivotToggle() {
if (pivotOpen.value) return
props.resource.anchorX = 0.5
props.resource.anchorY = 0.5
pivotFullscreen.value = false
}
function closePivotFullscreen(commit: boolean) {
if (commit) {
props.resource.anchorX = draftX.value