perf: 文本字体相关优化

This commit is contained in:
pipipi-pikachu 2024-12-29 17:29:22 +08:00
parent 77f150b354
commit c962d4af17
39 changed files with 69 additions and 143 deletions

View File

@ -32,7 +32,6 @@ if (import.meta.env.MODE !== 'development') {
onMounted(async () => { onMounted(async () => {
await deleteDiscardedDB() await deleteDiscardedDB()
snapshotStore.initSnapshotDatabase() snapshotStore.initSnapshotDatabase()
mainStore.setAvailableFonts()
}) })
// localStorage indexedDB ID // localStorage indexedDB ID

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +1,6 @@
$fontList: '仓耳小丸子', '优设标题黑', '字制区喜脉体', '峰广明锐体', '得意黑', '摄图摩登小方体', '站酷快乐体', '素材集市康康体', '素材集市酷方体', '途牛类圆体', '锐字真言体'; $fonts: 'SourceHanSans', 'SourceHanSerif', 'FangZhengHeiTi', 'FangZhengKaiTi', 'FangZhengShuSong', 'FangZhengFangSong', 'AlibabaPuHuiTi', 'ZhuQueFangSong', 'LXGWWenKai', 'WenDingPLKaiTi', 'DeYiHei', 'MiSans', 'CangerXiaowanzi', 'YousheTitleBlack', 'FengguangMingrui', 'ShetuModernSquare', 'ZcoolHappy', 'ZizhiQuXiMai', 'SucaiJishiKangkang', 'SucaiJishiCoolSquare', 'TuniuRounded', 'RuiziZhenyan';
@each $font in $fontList { @each $font in $fonts {
@font-face { @font-face {
font-display: swap; font-display: swap;
font-family: $font; font-family: $font;

View File

@ -2,6 +2,7 @@
outline: 0; outline: 0;
border: 0; border: 0;
font-size: 16px; font-size: 16px;
font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
word-break: break-word; word-break: break-word;
white-space: normal; white-space: normal;

View File

@ -1,44 +1,25 @@
export const SYS_FONTS = [ export const FONTS = [
{ label: 'Arial', value: 'Arial' }, { label: '默认字体', value: '' },
{ label: '微软雅黑', value: 'Microsoft Yahei' }, { label: '思源黑体', value: 'SourceHanSans' },
{ label: '宋体', value: 'SimSun' }, { label: '思源宋体', value: 'SourceHanSerif' },
{ label: '黑体', value: 'SimHei' }, { label: '方正黑体', value: 'FangZhengHeiTi' },
{ label: '楷体', value: 'KaiTi' }, { label: '方正楷体', value: 'FangZhengKaiTi' },
{ label: '新宋体', value: 'NSimSun' }, { label: '方正宋体', value: 'FangZhengShuSong' },
{ label: '仿宋', value: 'FangSong' }, { label: '方正仿宋', value: 'FangZhengFangSong' },
{ label: '苹方', value: 'PingFang SC' }, { label: '阿里巴巴普惠体', value: 'AlibabaPuHuiTi' },
{ label: '华文黑体', value: 'STHeiti' }, { label: '朱雀仿宋', value: 'ZhuqueFangSong' },
{ label: '华文楷体', value: 'STKaiti' }, { label: '霞鹜文楷', value: 'LXGWWenKai' },
{ label: '华文宋体', value: 'STSong' }, { label: '文鼎PL楷体', value: 'WenDingPLKaiTi' },
{ label: '华文仿宋', value: 'STFangSong' }, { label: '得意黑', value: 'DeYiHei' },
{ label: '华文中宋', value: 'STZhongSong' }, { label: 'MiSans', value: 'MiSans' },
{ label: '华文琥珀', value: 'STHupo' }, { label: '仓耳小丸子', value: 'CangerXiaowanzi' },
{ label: '华文新魏', value: 'STXinwei' }, { label: '优设标题黑', value: 'YousheTitleBlack' },
{ label: '华文隶书', value: 'STLiti' }, { label: '峰广明锐体', value: 'FengguangMingrui' },
{ label: '华文行楷', value: 'STXingkai' }, { label: '摄图摩登小方体', value: 'ShetuModernSquare' },
{ label: '冬青黑体', value: 'Hiragino Sans GB' }, { label: '站酷快乐体', value: 'ZcoolHappy' },
{ label: '兰亭黑', value: 'Lantinghei SC' }, { label: '字制区喜脉体', value: 'ZizhiQuXiMai' },
{ label: '偏偏体', value: 'Hanzipen SC' }, { label: '素材集市康康体', value: 'SucaiJishiKangkang' },
{ label: '手札体', value: 'Hannotate SC' }, { label: '素材集市酷方体', value: 'SucaiJishiCoolSquare' },
{ label: '宋体', value: 'Songti SC' }, { label: '途牛类圆体', value: 'TuniuRounded' },
{ label: '娃娃体', value: 'Wawati SC' }, { label: '锐字真言体', value: 'RuiziZhenyan' },
{ label: '行楷', value: 'Xingkai SC' },
{ label: '圆体', value: 'Yuanti SC' },
{ label: '华文细黑', value: 'STXihei' },
{ label: '幼圆', value: 'YouYuan' },
{ label: '隶书', value: 'LiSu' },
]
export const WEB_FONTS = [
{ label: '得意黑', value: '得意黑' },
{ label: '仓耳小丸子', value: '仓耳小丸子' },
{ label: '优设标题黑', value: '优设标题黑' },
{ label: '峰广明锐体', value: '峰广明锐体' },
{ label: '摄图摩登小方体', value: '摄图摩登小方体' },
{ label: '站酷快乐体', value: '站酷快乐体' },
{ label: '字制区喜脉体', value: '字制区喜脉体' },
{ label: '素材集市康康体', value: '素材集市康康体' },
{ label: '素材集市酷方体', value: '素材集市酷方体' },
{ label: '途牛类圆体', value: '途牛类圆体' },
{ label: '锐字真言体', value: '锐字真言体' },
] ]

View File

@ -9,85 +9,85 @@ export const PRESET_THEMES: PresetTheme[] = [
{ {
background: '#ffffff', background: '#ffffff',
fontColor: '#333333', fontColor: '#333333',
fontname: 'Microsoft Yahei', fontname: '',
colors: ['#5b9bd5', '#ed7d31', '#a5a5a5', '#ffc000', '#4472c4', '#70ad47'], colors: ['#5b9bd5', '#ed7d31', '#a5a5a5', '#ffc000', '#4472c4', '#70ad47'],
}, },
{ {
background: '#ffffff', background: '#ffffff',
fontColor: '#333333', fontColor: '#333333',
fontname: 'Microsoft Yahei', fontname: '',
colors: ['#83992a', '#3c9670', '#44709d', '#a23b32', '#d87728', '#deb340'], colors: ['#83992a', '#3c9670', '#44709d', '#a23b32', '#d87728', '#deb340'],
}, },
{ {
background: '#ffffff', background: '#ffffff',
fontColor: '#333333', fontColor: '#333333',
fontname: 'Microsoft Yahei', fontname: '',
colors: ['#e48312', '#bd582c', '#865640', '#9b8357', '#c2bc80', '#94a088'], colors: ['#e48312', '#bd582c', '#865640', '#9b8357', '#c2bc80', '#94a088'],
}, },
{ {
background: '#ffffff', background: '#ffffff',
fontColor: '#333333', fontColor: '#333333',
fontname: 'Microsoft Yahei', fontname: '',
colors: ['#bdc8df', '#003fa9', '#f5ba00', '#ff7567', '#7676d9', '#923ffc'], colors: ['#bdc8df', '#003fa9', '#f5ba00', '#ff7567', '#7676d9', '#923ffc'],
}, },
{ {
background: '#ffffff', background: '#ffffff',
fontColor: '#333333', fontColor: '#333333',
fontname: 'Microsoft Yahei', fontname: '',
colors: ['#90c225', '#54a121', '#e6b91e', '#e86618', '#c42f19', '#918756'], colors: ['#90c225', '#54a121', '#e6b91e', '#e86618', '#c42f19', '#918756'],
}, },
{ {
background: '#ffffff', background: '#ffffff',
fontColor: '#333333', fontColor: '#333333',
fontname: 'Microsoft Yahei', fontname: '',
colors: ['#1cade4', '#2683c6', '#27ced7', '#42ba97', '#3e8853', '#62a39f'], colors: ['#1cade4', '#2683c6', '#27ced7', '#42ba97', '#3e8853', '#62a39f'],
}, },
{ {
background: '#e9efd6', background: '#e9efd6',
fontColor: '#333333', fontColor: '#333333',
fontname: 'Microsoft Yahei', fontname: '',
colors: ['#a5300f', '#de7e18', '#9f8351', '#728653', '#92aa4c', '#6aac91'], colors: ['#a5300f', '#de7e18', '#9f8351', '#728653', '#92aa4c', '#6aac91'],
}, },
{ {
background: '#17444e', background: '#17444e',
fontColor: '#ffffff', fontColor: '#ffffff',
fontname: 'Microsoft Yahei', fontname: '',
colors: ['#b01513', '#ea6312', '#e6b729', '#6bab90', '#55839a', '#9e5d9d'], colors: ['#b01513', '#ea6312', '#e6b729', '#6bab90', '#55839a', '#9e5d9d'],
}, },
{ {
background: '#36234d', background: '#36234d',
fontColor: '#ffffff', fontColor: '#ffffff',
fontname: 'Microsoft Yahei', fontname: '',
colors: ['#b31166', '#e33d6f', '#e45f3c', '#e9943a', '#9b6bf2', '#d63cd0'], colors: ['#b31166', '#e33d6f', '#e45f3c', '#e9943a', '#9b6bf2', '#d63cd0'],
}, },
{ {
background: '#247fad', background: '#247fad',
fontColor: '#ffffff', fontColor: '#ffffff',
fontname: 'Microsoft Yahei', fontname: '',
colors: ['#052f61', '#a50e82', '#14967c', '#6a9e1f', '#e87d37', '#c62324'], colors: ['#052f61', '#a50e82', '#14967c', '#6a9e1f', '#e87d37', '#c62324'],
}, },
{ {
background: '#103f55', background: '#103f55',
fontColor: '#ffffff', fontColor: '#ffffff',
fontname: 'Microsoft Yahei', fontname: '',
colors: ['#40aebd', '#97e8d5', '#a1cf49', '#628f3e', '#f2df3a', '#fcb01c'], colors: ['#40aebd', '#97e8d5', '#a1cf49', '#628f3e', '#f2df3a', '#fcb01c'],
}, },
{ {
background: '#242367', background: '#242367',
fontColor: '#ffffff', fontColor: '#ffffff',
fontname: 'Microsoft Yahei', fontname: '',
colors: ['#ac3ec1', '#477bd1', '#46b298', '#90ba4c', '#dd9d31', '#e25345'], colors: ['#ac3ec1', '#477bd1', '#46b298', '#90ba4c', '#dd9d31', '#e25345'],
}, },
{ {
background: '#e4b75e', background: '#e4b75e',
fontColor: '#333333', fontColor: '#333333',
fontname: 'Microsoft Yahei', fontname: '',
colors: ['#f0a22e', '#a5644e', '#b58b80', '#c3986d', '#a19574', '#c17529'], colors: ['#f0a22e', '#a5644e', '#b58b80', '#c3986d', '#a19574', '#c17529'],
}, },
{ {
background: '#333333', background: '#333333',
fontColor: '#ffffff', fontColor: '#ffffff',
fontname: 'Microsoft Yahei', fontname: '',
colors: ['#bdc8df', '#003fa9', '#f5ba00', '#ff7567', '#7676d9', '#923ffc'], colors: ['#bdc8df', '#003fa9', '#f5ba00', '#ff7567', '#7676d9', '#923ffc'],
}, },
] ]

View File

@ -42,7 +42,7 @@ export const slides: Slide[] = [
lineHeight: 1.2, lineHeight: 1.2,
content: '<p><strong><span style=\"font-size: 112px;\">PPTist</span></strong></p>', content: '<p><strong><span style=\"font-size: 112px;\">PPTist</span></strong></p>',
rotate: 0, rotate: 0,
defaultFontName: 'Microsoft Yahei', defaultFontName: '',
defaultColor: '#333' defaultColor: '#333'
}, },
{ {
@ -54,7 +54,7 @@ export const slides: Slide[] = [
height: 56, height: 56,
content: '<p><span style=\"font-size: 24px;\">基于 Vue 3.x + TypeScript 的在线演示文稿应用</span></p>', content: '<p><span style=\"font-size: 24px;\">基于 Vue 3.x + TypeScript 的在线演示文稿应用</span></p>',
rotate: 0, rotate: 0,
defaultFontName: 'Microsoft Yahei', defaultFontName: '',
defaultColor: '#333' defaultColor: '#333'
}, },
{ {
@ -88,7 +88,7 @@ export const slides: Slide[] = [
lineHeight: 1.2, lineHeight: 1.2,
content: '<p style=\"text-align: center;\"><strong><span style=\"font-size: 48px;\">在此处添加标题</span></strong></p>', content: '<p style=\"text-align: center;\"><strong><span style=\"font-size: 48px;\">在此处添加标题</span></strong></p>',
rotate: 0, rotate: 0,
defaultFontName: 'Microsoft Yahei', defaultFontName: '',
defaultColor: '#333', defaultColor: '#333',
}, },
{ {
@ -100,7 +100,7 @@ export const slides: Slide[] = [
height: 56, height: 56,
content: '<p style=\"text-align: center;\"><span style=\"font-size: 24px;\">在此处添加副标题</span></p>', content: '<p style=\"text-align: center;\"><span style=\"font-size: 24px;\">在此处添加副标题</span></p>',
rotate: 0, rotate: 0,
defaultFontName: 'Microsoft Yahei', defaultFontName: '',
defaultColor: '#333', defaultColor: '#333',
}, },
{ {
@ -173,7 +173,7 @@ export const slides: Slide[] = [
height: 140, height: 140,
content: '<p style=\"text-align: center;\"><strong><span style=\"font-size: 80px;\"><span style=\"color: rgb(255, 255, 255);\">感谢观看</span></span></strong></p>', content: '<p style=\"text-align: center;\"><strong><span style=\"font-size: 80px;\"><span style=\"color: rgb(255, 255, 255);\">感谢观看</span></span></strong></p>',
rotate: 0, rotate: 0,
defaultFontName: 'Microsoft Yahei', defaultFontName: '',
defaultColor: '#333', defaultColor: '#333',
wordSpace: 5 wordSpace: 5
} }

View File

@ -3,7 +3,7 @@ import type { SlideTheme } from '@/types/slides'
export const theme: SlideTheme = { export const theme: SlideTheme = {
themeColor: '#5b9bd5', themeColor: '#5b9bd5',
fontColor: '#333', fontColor: '#333',
fontName: 'Microsoft Yahei', fontName: '',
backgroundColor: '#fff', backgroundColor: '#fff',
shadow: { shadow: {
h: 3, h: 3,

View File

@ -4,8 +4,6 @@ import { ToolbarStates } from '@/types/toolbar'
import type { CreatingElement, ShapeFormatPainter, TextFormatPainter } from '@/types/edit' import type { CreatingElement, ShapeFormatPainter, TextFormatPainter } from '@/types/edit'
import type { DialogForExportTypes } from '@/types/export' import type { DialogForExportTypes } from '@/types/export'
import { type TextAttrs, defaultRichTextAttrs } from '@/utils/prosemirror/utils' import { type TextAttrs, defaultRichTextAttrs } from '@/utils/prosemirror/utils'
import { SYS_FONTS } from '@/configs/font'
import { isSupportFont } from '@/utils/font'
import { useSlidesStore } from './slides' import { useSlidesStore } from './slides'
@ -24,7 +22,6 @@ export interface MainState {
showRuler: boolean showRuler: boolean
creatingElement: CreatingElement | null creatingElement: CreatingElement | null
creatingCustomShape: boolean creatingCustomShape: boolean
availableFonts: typeof SYS_FONTS
toolbarState: ToolbarStates toolbarState: ToolbarStates
clipingImageElementId: string clipingImageElementId: string
isScaling: boolean isScaling: boolean
@ -60,7 +57,6 @@ export const useMainStore = defineStore('main', {
showRuler: false, // 显示标尺 showRuler: false, // 显示标尺
creatingElement: null, // 正在插入的元素信息,需要通过绘制插入的元素(文字、形状、线条) creatingElement: null, // 正在插入的元素信息,需要通过绘制插入的元素(文字、形状、线条)
creatingCustomShape: false, // 正在绘制任意多边形 creatingCustomShape: false, // 正在绘制任意多边形
availableFonts: SYS_FONTS, // 当前环境可用字体
toolbarState: ToolbarStates.SLIDE_DESIGN, // 右侧工具栏状态 toolbarState: ToolbarStates.SLIDE_DESIGN, // 右侧工具栏状态
clipingImageElementId: '', // 当前正在裁剪的图片ID clipingImageElementId: '', // 当前正在裁剪的图片ID
richTextAttrs: defaultRichTextAttrs, // 富文本状态 richTextAttrs: defaultRichTextAttrs, // 富文本状态
@ -153,10 +149,6 @@ export const useMainStore = defineStore('main', {
this.creatingCustomShape = state this.creatingCustomShape = state
}, },
setAvailableFonts() {
this.availableFonts = SYS_FONTS.filter(font => isSupportFont(font.value))
},
setToolbarState(toolbarState: ToolbarStates) { setToolbarState(toolbarState: ToolbarStates) {
this.toolbarState = toolbarState this.toolbarState = toolbarState
}, },

View File

@ -1,36 +0,0 @@
/**
*
* @param fontName
*/
export const isSupportFont = (fontName: string) => {
if (typeof fontName !== 'string') return false
const arial = 'Arial'
if (fontName.toLowerCase() === arial.toLowerCase()) return true
const size = 100
const width = 100
const height = 100
const str = 'a'
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d', { willReadFrequently: true })
if (!ctx) return false
canvas.width = width
canvas.height = height
ctx.textAlign = 'center'
ctx.fillStyle = 'black'
ctx.textBaseline = 'middle'
const getDotArray = (_fontFamily: string) => {
ctx.clearRect(0, 0, width, height)
ctx.font = `${size}px ${_fontFamily}, ${arial}`
ctx.fillText(str, width / 2, height / 2)
const imageData = ctx.getImageData(0, 0, width, height).data
return [].slice.call(imageData).filter(item => item !== 0)
}
return getDotArray(arial).join('') !== getDotArray(fontName).join('')
}

View File

@ -187,7 +187,7 @@ const _defaultAttrs: DefaultAttrs = {
color: '#000000', color: '#000000',
backcolor: '', backcolor: '',
fontsize: '16px', fontsize: '16px',
fontname: '微软雅黑', fontname: '',
align: 'left', align: 'left',
} }
export const getTextAttrs = (view: EditorView, attrs: Partial<DefaultAttrs> = {}) => { export const getTextAttrs = (view: EditorView, attrs: Partial<DefaultAttrs> = {}) => {
@ -251,7 +251,7 @@ export const defaultRichTextAttrs: TextAttrs = {
color: '#000000', color: '#000000',
backcolor: '', backcolor: '',
fontsize: '16px', fontsize: '16px',
fontname: '微软雅黑', fontname: '',
link: '', link: '',
align: 'left', align: 'left',
bulletList: false, bulletList: false,

View File

@ -58,10 +58,7 @@
search search
searchLabel="搜索字体" searchLabel="搜索字体"
@update:value="value => updateFontStyle('fontname', value as string)" @update:value="value => updateFontStyle('fontname', value as string)"
:options="[ :options="FONTS"
...availableFonts,
...WEB_FONTS
]"
> >
<template #icon> <template #icon>
<IconFontSize /> <IconFontSize />
@ -139,7 +136,7 @@ import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store' import { useMainStore, useSlidesStore } from '@/store'
import type { LineStyleType, PPTElement, PPTElementOutline, TableCell } from '@/types/slides' import type { LineStyleType, PPTElement, PPTElementOutline, TableCell } from '@/types/slides'
import emitter, { EmitterEvents } from '@/utils/emitter' import emitter, { EmitterEvents } from '@/utils/emitter'
import { WEB_FONTS } from '@/configs/font' import { FONTS } from '@/configs/font'
import useHistorySnapshot from '@/hooks/useHistorySnapshot' import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import SVGLine from '../common/SVGLine.vue' import SVGLine from '../common/SVGLine.vue'
@ -158,7 +155,7 @@ import SelectCustom from '@/components/SelectCustom.vue'
import Popover from '@/components/Popover.vue' import Popover from '@/components/Popover.vue'
const slidesStore = useSlidesStore() const slidesStore = useSlidesStore()
const { richTextAttrs, availableFonts, activeElementList } = storeToRefs(useMainStore()) const { richTextAttrs, activeElementList } = storeToRefs(useMainStore())
const { addHistorySnapshot } = useHistorySnapshot() const { addHistorySnapshot } = useHistorySnapshot()

View File

@ -7,10 +7,7 @@
search search
searchLabel="搜索字体" searchLabel="搜索字体"
@update:value="value => updateTextAttrs({ fontname: value as string })" @update:value="value => updateTextAttrs({ fontname: value as string })"
:options="[ :options="FONTS"
...availableFonts,
...WEB_FONTS
]"
> >
<template #icon> <template #icon>
<IconFontSize /> <IconFontSize />
@ -178,7 +175,7 @@ import { storeToRefs } from 'pinia'
import { nanoid } from 'nanoid' import { nanoid } from 'nanoid'
import { useMainStore, useSlidesStore } from '@/store' import { useMainStore, useSlidesStore } from '@/store'
import type { PPTTableElement, TableCell, TableCellStyle, TableTheme, TextAlign } from '@/types/slides' import type { PPTTableElement, TableCell, TableCellStyle, TableTheme, TextAlign } from '@/types/slides'
import { WEB_FONTS } from '@/configs/font' import { FONTS } from '@/configs/font'
import useHistorySnapshot from '@/hooks/useHistorySnapshot' import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import ElementOutline from '../common/ElementOutline.vue' import ElementOutline from '../common/ElementOutline.vue'
@ -198,7 +195,7 @@ import SelectGroup from '@/components/SelectGroup.vue'
import Popover from '@/components/Popover.vue' import Popover from '@/components/Popover.vue'
const slidesStore = useSlidesStore() const slidesStore = useSlidesStore()
const { handleElement, handleElementId, selectedTableCells: selectedCells, availableFonts } = storeToRefs(useMainStore()) const { handleElement, handleElementId, selectedTableCells: selectedCells } = storeToRefs(useMainStore())
const themeColor = computed(() => slidesStore.theme.themeColor) const themeColor = computed(() => slidesStore.theme.themeColor)
const fontSizeOptions = [ const fontSizeOptions = [

View File

@ -131,10 +131,7 @@
search search
searchLabel="搜索字体" searchLabel="搜索字体"
@update:value="value => updateTheme({ fontName: value as string })" @update:value="value => updateTheme({ fontName: value as string })"
:options="[ :options="FONTS"
...availableFonts,
...WEB_FONTS
]"
/> />
</div> </div>
<div class="row"> <div class="row">
@ -303,7 +300,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store' import { useSlidesStore } from '@/store'
import type { import type {
Gradient, Gradient,
GradientType, GradientType,
@ -315,7 +312,7 @@ import type {
LineStyleType, LineStyleType,
} from '@/types/slides' } from '@/types/slides'
import { PRESET_THEMES } from '@/configs/theme' import { PRESET_THEMES } from '@/configs/theme'
import { WEB_FONTS } from '@/configs/font' import { FONTS } from '@/configs/font'
import useHistorySnapshot from '@/hooks/useHistorySnapshot' import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import useSlideTheme from '@/hooks/useSlideTheme' import useSlideTheme from '@/hooks/useSlideTheme'
import { getImageDataURL } from '@/utils/image' import { getImageDataURL } from '@/utils/image'
@ -336,7 +333,6 @@ import Modal from '@/components/Modal.vue'
import GradientBar from '@/components/GradientBar.vue' import GradientBar from '@/components/GradientBar.vue'
const slidesStore = useSlidesStore() const slidesStore = useSlidesStore()
const { availableFonts } = storeToRefs(useMainStore())
const { slides, currentSlide, viewportRatio, theme } = storeToRefs(slidesStore) const { slides, currentSlide, viewportRatio, theme } = storeToRefs(slidesStore)
const moreThemeConfigsVisible = ref(false) const moreThemeConfigsVisible = ref(false)

View File

@ -71,7 +71,7 @@
import { onMounted, ref, watch } from 'vue' import { onMounted, ref, watch } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useSlidesStore } from '@/store' import { useSlidesStore } from '@/store'
import { SYS_FONTS, WEB_FONTS } from '@/configs/font' import { FONTS } from '@/configs/font'
import useSlideTheme from '@/hooks/useSlideTheme' import useSlideTheme from '@/hooks/useSlideTheme'
import Tabs from '@/components/Tabs.vue' import Tabs from '@/components/Tabs.vue'
import Button from '@/components/Button.vue' import Button from '@/components/Button.vue'
@ -99,10 +99,7 @@ const activeTab = ref<'single' | 'all'>('single')
const fontMap = ref<{ [key: string]: string }>({}) const fontMap = ref<{ [key: string]: string }>({})
onMounted(() => { onMounted(() => {
const map: { [key: string]: string } = {} const map: { [key: string]: string } = {}
for (const item of SYS_FONTS) { for (const item of FONTS) {
map[item.value] = item.label
}
for (const item of WEB_FONTS) {
map[item.value] = item.label map[item.value] = item.label
} }
fontMap.value = map fontMap.value = map

View File

@ -8,10 +8,7 @@
search search
searchLabel="搜索字体" searchLabel="搜索字体"
@update:value="value => emitRichTextCommand('fontname', value as string)" @update:value="value => emitRichTextCommand('fontname', value as string)"
:options="[ :options="FONTS"
...availableFonts,
...WEB_FONTS
]"
> >
<template #icon> <template #icon>
<IconFontSize /> <IconFontSize />
@ -253,7 +250,7 @@ import { ref, watch } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store' import { useMainStore } from '@/store'
import emitter, { EmitterEvents } from '@/utils/emitter' import emitter, { EmitterEvents } from '@/utils/emitter'
import { WEB_FONTS } from '@/configs/font' import { FONTS } from '@/configs/font'
import useTextFormatPainter from '@/hooks/useTextFormatPainter' import useTextFormatPainter from '@/hooks/useTextFormatPainter'
import message from '@/utils/message' import message from '@/utils/message'
@ -271,7 +268,7 @@ import RadioButton from '@/components/RadioButton.vue'
import RadioGroup from '@/components/RadioGroup.vue' import RadioGroup from '@/components/RadioGroup.vue'
import PopoverMenuItem from '@/components/PopoverMenuItem.vue' import PopoverMenuItem from '@/components/PopoverMenuItem.vue'
const { richTextAttrs, availableFonts, textFormatPainter } = storeToRefs(useMainStore()) const { richTextAttrs, textFormatPainter } = storeToRefs(useMainStore())
const { toggleTextFormatPainter } = useTextFormatPainter() const { toggleTextFormatPainter } = useTextFormatPainter()

View File

@ -22,6 +22,7 @@ import { indentCommand, textIndentCommand } from '@/utils/prosemirror/commands/s
import { toggleList } from '@/utils/prosemirror/commands/toggleList' import { toggleList } from '@/utils/prosemirror/commands/toggleList'
import { setListStyle } from '@/utils/prosemirror/commands/setListStyle' import { setListStyle } from '@/utils/prosemirror/commands/setListStyle'
import type { TextFormatPainterKeys } from '@/types/edit' import type { TextFormatPainterKeys } from '@/types/edit'
import message from '@/utils/message'
import { KEYS } from '@/configs/hotkey' import { KEYS } from '@/configs/hotkey'
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
@ -118,10 +119,14 @@ const execCommand = ({ target, action }: RichTextCommand) => {
const actions = ('command' in action) ? [action] : action const actions = ('command' in action) ? [action] : action
for (const item of actions) { for (const item of actions) {
if (item.command === 'fontname' && item.value) { if (item.command === 'fontname' && item.value !== undefined) {
const mark = editorView.state.schema.marks.fontname.create({ fontname: item.value }) const mark = editorView.state.schema.marks.fontname.create({ fontname: item.value })
autoSelectAll(editorView) autoSelectAll(editorView)
addMark(editorView, mark) addMark(editorView, mark)
if (item.value && !document.fonts.check(`16px ${item.value}`)) {
message.warning('字体需要等待加载下载后生效,请稍等')
}
} }
else if (item.command === 'fontsize' && item.value) { else if (item.command === 'fontsize' && item.value) {
const mark = editorView.state.schema.marks.fontsize.create({ fontsize: item.value }) const mark = editorView.state.schema.marks.fontsize.create({ fontsize: item.value })