feat. [SWV-807] 게임 폰트 기능 추가

This commit is contained in:
clkim
2026-01-16 14:52:14 +09:00
parent ea5f31acff
commit c8cd7f780e
5 changed files with 113 additions and 53 deletions

View File

@@ -3,87 +3,129 @@ import { useNuxtApp } from 'nuxt/app'
import type {
GameDataMetaTag,
GameDataValue,
GameDataKeyColors,
GameDataImg,
} from '#layers/types/api/gameData'
const nuxtApp = useNuxtApp()
const { locale } = useI18n()
const gameDataStore = useGameDataStore()
const modalStore = useModalStore()
const scrollStore = useScrollStore()
const { setGameData } = gameDataStore
const { gameName, gaCode } = storeToRefs(gameDataStore)
const { confirm, alert } = modalStore
const { gameName, gaCode } = storeToRefs(gameDataStore)
const { scrollGnbPosition } = storeToRefs(scrollStore)
// 통합 메타데이터 설정
const setupAllMetaData = (data: GameDataValue) => {
const meta = data.meta_tag_json ?? ({} as GameDataMetaTag)
const faviconPath = data.favicon_json ?? ({} as GameDataImg)
const theme = data.design_theme === 1 ? 'light' : 'dark'
// favicon 링크 생성 헬퍼
const createStyleLinks = (faviconJson: GameDataImg, fontPath: string = '') => {
const links = []
const iconUrl = faviconJson[0]
const appleTouchIconUrl = faviconJson[1]
const pngIconUrl = faviconJson[2]
// 파비콘 링크 생성
const faviconLinks = [
{
if (iconUrl) {
links.push({
rel: 'icon',
type: 'image/x-icon',
href: formatPathHost(faviconPath[0]),
},
{
href: formatPathHost(iconUrl),
})
}
if (appleTouchIconUrl) {
links.push({
rel: 'apple-touch-icon',
href: formatPathHost(faviconPath[1]),
},
{
href: formatPathHost(appleTouchIconUrl),
})
}
if (pngIconUrl) {
links.push({
rel: 'icon',
type: 'image/png',
href: formatPathHost(faviconPath[2]),
href: formatPathHost(pngIconUrl),
})
}
if (fontPath) {
links.push({
rel: 'stylesheet',
href: formatPathHost(fontPath),
})
}
return links
}
// 메타 태그 생성 헬퍼
const createMetaTags = (metaTag: Partial<GameDataMetaTag> = {}) => {
const metaList = [
{ name: 'description', content: metaTag.page_desc },
{ property: 'og:title', content: metaTag.og_title },
{ property: 'og:description', content: metaTag.og_desc },
{
property: 'og:image',
content: formatPathHost(metaTag.og_image),
},
{ name: 'twitter:title', content: metaTag.x_title },
{ name: 'twitter:description', content: metaTag.x_desc },
{
name: 'twitter:image',
content: formatPathHost(metaTag.x_image),
},
]
// 색상 CSS 변수 생성
const cssColorVariables = Object.entries(data.key_color_json ?? {})
// content가 유효한 메타 태그만 필터링
return metaList.filter(
meta => meta.content && String(meta.content).trim() !== ''
)
}
// CSS 변수 생성 헬퍼
const createCssVariable = (keyColorJson: GameDataKeyColors) => {
const colorVariables = Object.entries(keyColorJson)
.filter(([key, value]) => key && value != null)
.map(([key, value]) => `--${key}: ${value};`)
.join('\n ')
const cssContent = `
:root {
${cssColorVariables}
}
`
return `:root {${colorVariables}}`
}
useHead({
title: meta?.page_title ?? '',
meta: [
{ name: 'description', content: meta.page_desc },
{ property: 'og:title', content: meta.og_title },
{ property: 'og:description', content: meta.og_desc },
{ property: 'og:image', content: formatPathHost(meta.og_image) },
{ name: 'twitter:title', content: meta.x_title },
{ name: 'twitter:description', content: meta.x_desc },
{ name: 'twitter:image', content: formatPathHost(meta.x_image) },
],
htmlAttrs: {
'data-game': data.game_name || '',
'data-theme': theme,
lang: locale.value ?? data.default_lang_code,
},
link: faviconLinks,
style: [
{
innerHTML: cssContent,
id: 'game-css-variables',
// 게임 헤드 설정
const setupGameHead = (data: GameDataValue) => {
try {
const metaTag: Partial<GameDataMetaTag> = data.meta_tag_json ?? {}
const designTheme = data.design_theme === 1 ? 'light' : 'dark'
const styleLinks = createStyleLinks(
data.favicon_json
// data?.game_font?.font_path
)
useHead({
title: metaTag.page_title ?? '',
meta: createMetaTags(metaTag),
htmlAttrs: {
'data-game': data.game_name ?? '',
'data-theme': designTheme,
lang: locale.value ?? data.default_lang_code ?? 'ko',
},
],
})
link: styleLinks,
style: [
{
innerHTML: createCssVariable(data.key_color_json),
id: 'game-css-variables',
},
],
})
} catch (error) {
// eslint-disable-next-line no-console
console.error('[setupGameHead] Failed to setup game head:', error)
}
}
if (import.meta.server) {
const gameData = nuxtApp.ssrContext?.event?.context?.gameData
if (gameData) {
setGameData(gameData)
setupAllMetaData(gameData)
setupGameHead(gameData)
}
}