feat(font): 添加本地字体选择功能(not done) #96
This commit is contained in:
51
src/hooks/useLocalFonts.ts
Normal file
51
src/hooks/useLocalFonts.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
export function useLocalFonts() {
|
||||
const fonts = ref<Map<string, { name: string, value: string }[]>>(new Map())
|
||||
const disabled = ref(false)
|
||||
|
||||
const formatFonts = (list: FontData[]): Map<string, { name: string, value: string }[]> => {
|
||||
const res: Map<string, { name: string, value: string }[]> = new Map()
|
||||
for (const item of list) {
|
||||
if (!res.has(item.family)) {
|
||||
res.set(item.family, [])
|
||||
}
|
||||
|
||||
const fontArray = res.get(item.family)
|
||||
if (!Array.isArray(fontArray)) {
|
||||
continue
|
||||
}
|
||||
if (item.family === item.fullName) {
|
||||
fontArray.push({ name: item.style, value: item.fullName })
|
||||
continue
|
||||
}
|
||||
const name = item.fullName.replace(item.family, '').trim()
|
||||
const value = item.fullName
|
||||
fontArray.push({ name, value })
|
||||
}
|
||||
return res
|
||||
}
|
||||
const getFonts = async () => {
|
||||
if (!window.queryLocalFonts) {
|
||||
return
|
||||
}
|
||||
const list = await window.queryLocalFonts()
|
||||
console.log('list', list)
|
||||
const res = formatFonts(list)
|
||||
console.log('fontlist', res)
|
||||
fonts.value = res
|
||||
// 对比family,相同则移入第一个元素的children里面
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (!window.queryLocalFonts) {
|
||||
disabled.value = true
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
disabled,
|
||||
fonts,
|
||||
getFonts,
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ export const useGlobalConfig = defineStore('global', {
|
||||
patternColor: '#1b66c9',
|
||||
patternList: defaultPatternList as number[],
|
||||
background: {}, // 背景颜色或图片
|
||||
font: '',
|
||||
},
|
||||
musicList: defaultMusicList as IMusic[],
|
||||
imageList: defaultImageList as IImage[],
|
||||
@@ -106,6 +107,10 @@ export const useGlobalConfig = defineStore('global', {
|
||||
getBackground(state) {
|
||||
return state.globalConfig.theme.background
|
||||
},
|
||||
// 获取字体
|
||||
getFont(state) {
|
||||
return state.globalConfig.theme.font
|
||||
},
|
||||
// 获取是否显示头像
|
||||
getIsShowAvatar(state) {
|
||||
return state.globalConfig.isShowAvatar
|
||||
@@ -232,6 +237,10 @@ export const useGlobalConfig = defineStore('global', {
|
||||
setBackground(background: any) {
|
||||
this.globalConfig.theme.background = background
|
||||
},
|
||||
// 设置字体
|
||||
setFont(font: any) {
|
||||
this.globalConfig.theme.font = font
|
||||
},
|
||||
// 设置是否显示头像
|
||||
setIsShowAvatar(isShowAvatar: boolean) {
|
||||
this.globalConfig.isShowAvatar = isShowAvatar
|
||||
@@ -256,6 +265,7 @@ export const useGlobalConfig = defineStore('global', {
|
||||
patternColor: '#1b66c9',
|
||||
patternList: defaultPatternList as number[],
|
||||
background: {}, // 背景颜色或图片
|
||||
font: '',
|
||||
},
|
||||
musicList: defaultMusicList as IMusic[],
|
||||
imageList: defaultImageList as IImage[],
|
||||
|
||||
3
src/utils/format/tree.ts
Normal file
3
src/utils/format/tree.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
/**
|
||||
* @description 用于将平铺的数组组合到树形数组中
|
||||
*/
|
||||
@@ -6,6 +6,7 @@ import { useI18n } from 'vue-i18n'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { z as zod } from 'zod'
|
||||
import { daisyuiThemes } from '@/constant/theme'
|
||||
import { useLocalFonts } from '@/hooks/useLocalFonts'
|
||||
import i18n, { languageList } from '@/locales/i18n'
|
||||
import useStore from '@/store'
|
||||
import { themeChange } from '@/utils'
|
||||
@@ -18,9 +19,10 @@ const { t } = useI18n()
|
||||
const globalConfig = useStore().globalConfig
|
||||
const personConfig = useStore().personConfig
|
||||
const prizeConfig = useStore().prizeConfig
|
||||
const { getTopTitle: topTitle, getTheme: localTheme, getPatterColor: patternColor, getPatternList: patternList, getCardColor: cardColor, getLuckyColor: luckyCardColor, getTextColor: textColor, getCardSize: cardSize, getTextSize: textSize, getRowCount: rowCount, getIsShowPrizeList: isShowPrizeList, getLanguage: userLanguage, getBackground: backgroundImage, getImageList: imageList, getIsShowAvatar: isShowAvatar,
|
||||
const { getTopTitle: topTitle, getTheme: localTheme, getPatterColor: patternColor, getPatternList: patternList, getCardColor: cardColor, getLuckyColor: luckyCardColor, getTextColor: textColor, getCardSize: cardSize, getTextSize: textSize, getRowCount: rowCount, getIsShowPrizeList: isShowPrizeList, getLanguage: userLanguage, getBackground: backgroundImage, getFont: currentFont, getImageList: imageList, getIsShowAvatar: isShowAvatar,
|
||||
} = storeToRefs(globalConfig)
|
||||
const { getAlreadyPersonList: alreadyPersonList, getNotPersonList: notPersonList } = storeToRefs(personConfig)
|
||||
const { getFonts, disabled: disabledFonts, fonts } = useLocalFonts()
|
||||
const colorPickerRef = ref()
|
||||
const resetDataDialogRef = ref()
|
||||
interface ThemeDaType {
|
||||
@@ -42,6 +44,7 @@ const patternColorValue = ref(structuredClone(patternColor.value))
|
||||
const themeList = ref(daisyuiThemes)
|
||||
const daisyuiThemeList = ref<ThemeDaType>(daisyuiThemes)
|
||||
const backgroundImageValue = ref(backgroundImage.value)
|
||||
const currentFontValue = ref(currentFont.value)
|
||||
const formData = ref({
|
||||
rowCount: rowCountValue,
|
||||
})
|
||||
@@ -150,6 +153,10 @@ watch(isShowPrizeListValue, () => {
|
||||
watch(backgroundImageValue, (val) => {
|
||||
globalConfig.setBackground(val)
|
||||
})
|
||||
watch(currentFontValue, (val) => {
|
||||
console.log('currentFontValue', val)
|
||||
globalConfig.setFont(val)
|
||||
})
|
||||
watch(languageValue, (val: string) => {
|
||||
globalConfig.setLanguage(val)
|
||||
})
|
||||
@@ -225,6 +232,16 @@ onMounted(() => {
|
||||
class="w-full max-w-xs input input-bordered"
|
||||
>
|
||||
</label>
|
||||
|
||||
<label class="w-full max-w-xs form-control">
|
||||
<div class="label">
|
||||
<span class="label-text">字体</span>
|
||||
</div>
|
||||
<select v-model="currentFontValue" class="w-full max-w-xs border-solid select border-1" @click="getFonts">
|
||||
<option disabled selected>选择字体</option>
|
||||
<option v-for="item in fonts" :key="item.fullName" :style="{ fontFamily: `${item.fullName}`, fontSize: 'normal', fontWeight: 'normal' }" :value="item.fullName">{{ item.fullName }}</option>
|
||||
</select>
|
||||
</label>
|
||||
</fieldset>
|
||||
<!-- 布局设置(列数、卡片宽度、卡片高度 -->
|
||||
<fieldset class="p-4 border text-setting fieldset bg-base-200 border-base-300 rounded-box w-xs">
|
||||
|
||||
@@ -1,51 +1,76 @@
|
||||
<script setup lang='ts'>
|
||||
import { Grip } from 'lucide-vue-next'
|
||||
import { onMounted, ref, watch } from 'vue'
|
||||
import { VueDraggable } from 'vue-draggable-plus'
|
||||
import { ChevronDown, ChevronUp } from 'lucide-vue-next'
|
||||
import { ref } from 'vue'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
import { useLocalFonts } from '@/hooks/useLocalFonts'
|
||||
|
||||
const list = ref([
|
||||
{
|
||||
name: 'Joao',
|
||||
id: '1',
|
||||
},
|
||||
{
|
||||
name: 'Jean',
|
||||
id: '2',
|
||||
},
|
||||
{
|
||||
name: 'Johanna',
|
||||
id: '3',
|
||||
},
|
||||
{
|
||||
name: 'Juan',
|
||||
id: '4',
|
||||
},
|
||||
])
|
||||
onMounted(() => {
|
||||
const inputRef = ref()
|
||||
|
||||
})
|
||||
const { getFonts, disabled, fonts } = useLocalFonts()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<button class="btn btn-error">
|
||||
打印
|
||||
</button>
|
||||
<VueDraggable
|
||||
v-model="list"
|
||||
:animation="150"
|
||||
handle=".handle"
|
||||
class="flex flex-col gap-2 p-4 w-300px bg-gray-500/5 rounded"
|
||||
>
|
||||
<div
|
||||
v-for="(item, index) in list"
|
||||
:key="item.id"
|
||||
class="h-50px bg-gray-500/5 px-2 rounded flex items-center justify-between"
|
||||
>
|
||||
<Grip class="handle cursor-move" />
|
||||
<input v-model="item.name" type="text">
|
||||
</div>
|
||||
</VueDraggable>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="text-2xl">
|
||||
code
|
||||
</div>
|
||||
<div class="text-2xl" style="font-family: 'Consolas Bold Italic';">
|
||||
code
|
||||
</div>
|
||||
<font-select id="font-select-1" value="" style="display: initial;" />
|
||||
</div>
|
||||
<div class="w-full h-full flex justify-center items-center">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<label class="input cursor-default!" @click="getFonts">
|
||||
<input ref="inputRef" type="search" class="grow" placeholder="Search">
|
||||
<ChevronDown class="cursor-default" @click="inputRef.focus()" />
|
||||
<ChevronUp class="cursor-default" @click="inputRef.focus()" />
|
||||
</label>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent class="w-56" align="start">
|
||||
<DropdownMenuLabel>My Account</DropdownMenuLabel>
|
||||
<DropdownMenuGroup>
|
||||
<!-- <DropdownMenuItem v-for="[key, value] in Array.from(fonts)" :key="key" :style="{ fontFamily: `${key}` }">
|
||||
{{ key }}
|
||||
</DropdownMenuItem> -->
|
||||
<DropdownMenuSub v-for="[key, children] in Array.from(fonts)" :key="key">
|
||||
<DropdownMenuSubTrigger>
|
||||
<span :style="{ fontFamily: `${key}` }">{{ key }}</span>
|
||||
</DropdownMenuSubTrigger>
|
||||
<DropdownMenuPortal>
|
||||
<DropdownMenuSubContent>
|
||||
<DropdownMenuItem v-for="child in children" :key="child.value">
|
||||
<span :style="{ fontFamily: `${child.value}` }">{{ child.name }}</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuPortal>
|
||||
</DropdownMenuSub>
|
||||
<DropdownMenuItem>
|
||||
New Team
|
||||
<DropdownMenuShortcut>⌘+T</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>GitHub</DropdownMenuItem>
|
||||
<DropdownMenuItem>Support</DropdownMenuItem>
|
||||
<DropdownMenuItem disabled>
|
||||
API
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>
|
||||
Log out
|
||||
<DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
12
src/window.d.ts
vendored
Normal file
12
src/window.d.ts
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
// src/types/window.d.ts
|
||||
interface FontData {
|
||||
family: string
|
||||
fullName: string
|
||||
postscriptName: string
|
||||
style: string
|
||||
blob: () => Promise<Blob>
|
||||
}
|
||||
|
||||
interface Window {
|
||||
queryLocalFonts?: (options?) => Promise<FontData[]>
|
||||
}
|
||||
Reference in New Issue
Block a user