mirror of
https://github.com/palxiao/poster-design.git
synced 2025-07-15 16:02:19 +08:00
code: fonts optimization
This commit is contained in:
parent
6d00a04bfd
commit
c3d34bc35e
14
README.md
14
README.md
@ -109,18 +109,14 @@ A:考虑到服务端的开发语言、数据库类型都可能不尽相同,
|
||||
|
||||
或许你在工作中有类似的需求,或许你也对开发编辑器感兴趣,希望这个项目能给到你一些微薄帮助!
|
||||
|
||||
目前本项目也还在迭代中,有很多的不足,我也是一边学习一边成长。开源不易,希望看到这里的你可以给本项目点个 **Star** 支持一下~
|
||||
目前本项目也还在迭代中,有很多的不足,我也是一边学习一边成长。
|
||||
|
||||
[ -> 实时迭代计划文档](https://xp.palxp.cn/#/articles/1689319986889?id=%e8%bf%ad%e4%bb%a3%e8%ae%a1%e5%88%92)
|
||||
|
||||
开源不易,别忘了给本项目点个 **Star** 支持一下~
|
||||
|
||||
[](https://star-history.com/#palxiao/poster-design&Date)
|
||||
|
||||
#### 部分迭代计划:
|
||||
|
||||
- [ ] P1: 文字特效属性编辑面板开发
|
||||
- [ ] P1:字体抽取功能
|
||||
- [ ] P1:PSD 解析重构(涉及基础库更换)
|
||||
|
||||
[ -> 完整后续迭代计划文档](https://xp.palxp.cn/#/articles/1689319986889?id=%e8%bf%ad%e4%bb%a3%e8%ae%a1%e5%88%92)
|
||||
|
||||
### LICENSE
|
||||
|
||||
[MIT License](https://github.com/palxiao/poster-design/blob/main/LICENSE)
|
||||
|
@ -3,7 +3,7 @@
|
||||
* @Date: 2021-08-27 14:42:15
|
||||
* @Description: AI相关接口
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2023-09-30 12:08:01
|
||||
* @LastEditTime: 2023-10-13 00:07:19
|
||||
*/
|
||||
import fetch from '@/utils/axios'
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* @Date: 2021-08-27 14:42:15
|
||||
* @Description: 媒体相关接口
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2023-09-28 11:24:13
|
||||
* @LastEditTime: 2023-10-13 00:25:25
|
||||
*/
|
||||
import fetch from '@/utils/axios'
|
||||
|
||||
@ -15,7 +15,7 @@ export const getList = (params: Type.Object = {}) => fetch('design/material', pa
|
||||
|
||||
// 获取字体
|
||||
export const getFonts = (params: Type.Object = {}) => fetch('design/fonts', params)
|
||||
export const getFontSub = (params: Type.Object = {}) => fetch('design/font_sub', params)
|
||||
export const getFontSub = (params: Type.Object = {}, extra: any = {}) => fetch('design/font_sub', params, 'get', {}, extra)
|
||||
|
||||
// 图库列表
|
||||
export const getImagesList = (params: Type.Object = {}) => fetch('design/imgs', params, 'get')
|
||||
|
@ -15,6 +15,7 @@ body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
color: #333333;
|
||||
font-family: Hiragino Sans GB, Hiragino Sans GB W3, Arial, Microsoft Yahei, STHeiti, sans-serif;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
* {
|
||||
|
@ -2,12 +2,13 @@
|
||||
* @Author: ShawnPhang
|
||||
* @Date: 2022-01-08 09:43:37
|
||||
* @Description: 字体处理
|
||||
* @LastEditors: ShawnPhang <site: book.palxp.com>
|
||||
* @LastEditTime: 2023-07-25 11:13:01
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2023-10-13 01:30:33
|
||||
*/
|
||||
// import { isSupportFontFamily, blob2Base64 } from './utils'
|
||||
import { getFonts } from '@/api/material'
|
||||
// import store from '@/store'
|
||||
|
||||
const nowVersion = '2' // 当前字体文件版本更新,将刷新前端缓存
|
||||
|
||||
const fontList: any = []
|
||||
// const download: any = {}
|
||||
@ -16,7 +17,7 @@ export const useFontStore = {
|
||||
// download,
|
||||
async init() {
|
||||
this.list = []
|
||||
localStorage.getItem('FONTS_VERSION') !== '1' && localStorage.removeItem('FONTS')
|
||||
localStorage.getItem('FONTS_VERSION') !== nowVersion && localStorage.removeItem('FONTS')
|
||||
const localFonts: any = localStorage.getItem('FONTS') ? JSON.parse(localStorage.getItem('FONTS') || '') : []
|
||||
if (localFonts.length > 0) {
|
||||
this.list.push(...localFonts)
|
||||
@ -26,12 +27,12 @@ export const useFontStore = {
|
||||
const res = await getFonts({ pageSize: 400 })
|
||||
this.list.unshift(
|
||||
...res.list.map((x: any) => {
|
||||
const { alias, oid, value, preview, woff, lang } = x
|
||||
return { id: oid, value, preview, alias, url: woff, lang }
|
||||
const { id, alias, oid, value, preview, woff, lang } = x
|
||||
return { id, oid, value, preview, alias, url: woff, lang }
|
||||
}),
|
||||
)
|
||||
localStorage.setItem('FONTS', JSON.stringify(this.list))
|
||||
localStorage.setItem('FONTS_VERSION', '1')
|
||||
localStorage.setItem('FONTS_VERSION', nowVersion)
|
||||
}
|
||||
// store.dispatch('setFonts', this.list)
|
||||
},
|
||||
|
@ -77,7 +77,7 @@ export function filterSkyFonts() {
|
||||
// );
|
||||
const textClouds: any = []
|
||||
|
||||
;((textClouds as unknown) as CloudText[]).forEach((cloud) => {
|
||||
;(textClouds as unknown as CloudText[]).forEach((cloud) => {
|
||||
// 找到文字组件字体
|
||||
if (cloud.fontFamily && !fonts.includes(cloud.fontFamily)) {
|
||||
fonts.push(cloud.fontFamily)
|
||||
@ -114,6 +114,10 @@ export function base642Blob(b64Data: string, contentType = '', sliceSize = 512)
|
||||
|
||||
export async function blob2Base64(blob: Blob): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (blob.type === 'application/json') {
|
||||
resolve('')
|
||||
return
|
||||
}
|
||||
const fileReader = new FileReader()
|
||||
fileReader.onload = () => {
|
||||
resolve(fileReader.result as string)
|
||||
|
@ -3,7 +3,7 @@
|
||||
* @Date: 2022-02-11 18:48:23
|
||||
* @Description: 组件列表
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2023-10-08 22:57:34
|
||||
* @LastEditTime: 2023-10-13 18:48:25
|
||||
-->
|
||||
<template>
|
||||
<div class="wrap">
|
||||
@ -15,7 +15,7 @@
|
||||
<div class="header">其它</div>
|
||||
<div class="item" @click="openImageCutout">
|
||||
<i class="icon sd-AI_zhineng" />
|
||||
<div class="text"><span>在线抠图</span> <span class="desc">上传图像一键去除背景</span></div>
|
||||
<div class="text"><span>智能抠图</span> <span class="desc">上传图像一键去除背景</span></div>
|
||||
</div>
|
||||
<imageCutout ref="imageCutout" />
|
||||
</div>
|
||||
|
@ -1,28 +1,15 @@
|
||||
<!--
|
||||
* @Author: ShawnPhang
|
||||
* @Date: 2021-08-02 19:10:06
|
||||
* @Description:
|
||||
* @LastEditors: ShawnPhang
|
||||
* @LastEditTime: 2022-04-07 14:29:42
|
||||
* @Description: 选项选择(未拆分字体选择器)
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2023-10-14 21:03:17
|
||||
-->
|
||||
<template>
|
||||
<div id="value-select" ref="select" :style="{ width: inputWidth }">
|
||||
<p v-if="label" class="input-label">
|
||||
{{ label }}
|
||||
</p>
|
||||
<!-- <div class="input-wrap" :class="{ active: inputBorder }" :style="{ width: inputWidth }">
|
||||
<input class="real-input" :style="{ textAlign: textAlign }" :class="{ disable: !disable }" :readonly="readonly ? 'readonly' : ''" type="text" :value="showValue" @input="innerValue = $event.target.value.replace(RegExp(suffix), '')" @focus="inputBorder = true" @blur="inputBorder = false" />
|
||||
<div class="op-btn">
|
||||
<div class="down" @click="inputBorder = !inputBorder"></div>
|
||||
</div>
|
||||
</div>
|
||||
<el-popover ref="list" v-model="inputBorder" placement="bottom-start" trigger="click" :width="width" popper-class="value-select-list">
|
||||
<ul v-if="data" class="list-ul">
|
||||
<li v-for="listItem in data" :key="typeof listItem === 'object' ? listItem.name : listItem" :class="{ active: listItem == innerValue }" @click="selectItem(listItem)">
|
||||
{{ (typeof listItem === 'object' ? listItem.name : listItem) + suffix }}
|
||||
</li>
|
||||
</ul>
|
||||
</el-popover> -->
|
||||
<el-popover placement="bottom-end" width="auto">
|
||||
<!-- 单列表 -->
|
||||
<ul v-if="data && Array.isArray(data)" class="list-ul">
|
||||
@ -32,16 +19,18 @@
|
||||
</li>
|
||||
</ul>
|
||||
<!-- tab分类列表 -->
|
||||
<el-tabs v-else v-model="activeTab">
|
||||
<el-tab-pane v-for="(val, key, i) in data" :key="'tab' + i" :label="key" :name="key">
|
||||
<ul class="list-ul">
|
||||
<li v-for="listItem in data[key]" :key="typeof listItem === 'object' ? listItem.alias : listItem" :class="{ active: listItem == innerValue }" @click="selectItem(listItem)">
|
||||
<img v-if="listItem.preview" class="preview" :src="listItem.preview" />
|
||||
<span v-else>{{ (typeof listItem === 'object' ? listItem.alias : listItem) + suffix }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<div v-else class="tabs-wrap">
|
||||
<el-tabs v-model="activeTab">
|
||||
<el-tab-pane v-for="(val, key, i) in data" :key="'tab' + i" :label="key" :name="key">
|
||||
<ul class="list-ul">
|
||||
<li v-for="listItem in data[key]" :key="typeof listItem === 'object' ? listItem.alias : listItem" :class="{ active: listItem == innerValue }" @click="selectItem(listItem)">
|
||||
<img v-if="listItem.preview" class="preview" :src="listItem.preview" />
|
||||
<span v-else :style="{ fontFamily: `'${listItem.value}'` }">{{ (typeof listItem === 'object' ? listItem.alias : listItem) + suffix }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<template #reference>
|
||||
<div :class="['input-wrap', { active: inputBorder }]" :style="{ width: inputWidth }">
|
||||
<!-- <img v-if="innerPreview" class="preview" :src="innerPreview" /> -->
|
||||
@ -298,4 +287,8 @@ export default {
|
||||
height: 1.6em;
|
||||
}
|
||||
}
|
||||
|
||||
.tabs-wrap {
|
||||
width: 210px;
|
||||
}
|
||||
</style>
|
||||
|
22
src/components/modules/widgets/wText/pageFontsFilter.ts
Normal file
22
src/components/modules/widgets/wText/pageFontsFilter.ts
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* @Author: ShawnPhang
|
||||
* @Date: 2023-10-14 20:16:48
|
||||
* @Description: 找出页面中使用的字体
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2023-10-14 20:29:26
|
||||
*/
|
||||
import store from '@/store'
|
||||
import { toRaw } from 'vue'
|
||||
export default () => {
|
||||
const collector = new Set()
|
||||
const fonts: any = {}
|
||||
const { dWidgets: widgets } = store.getters
|
||||
for (let i = 0; i < widgets.length; i++) {
|
||||
const { type, fontClass } = widgets[i]
|
||||
if (type === 'w-text') {
|
||||
collector.add(fontClass.id)
|
||||
fonts[fontClass.id] = toRaw(fontClass)
|
||||
}
|
||||
}
|
||||
return Array.from(collector).map((id: any) => fonts[id])
|
||||
}
|
@ -70,10 +70,10 @@ export default {
|
||||
fontSize: 24,
|
||||
zoom: 1,
|
||||
fontClass: {
|
||||
alias: '素材集市酷方体',
|
||||
id: 33925853,
|
||||
value: 'sucaijishikufangti',
|
||||
url: 'https://res.palxp.cn/static/fonts/20200809-152508-8654.woff',
|
||||
alias: '站酷快乐体',
|
||||
id: 543,
|
||||
value: 'zcool-kuaile-regular',
|
||||
url: 'https://lib.baomitu.com/fonts/zcool-kuaile/zcool-kuaile-regular.woff2',
|
||||
},
|
||||
fontFamily: 'SourceHanSansSC-Regular',
|
||||
fontWeight: 'normal',
|
||||
|
@ -51,8 +51,8 @@
|
||||
<script>
|
||||
// 文本组件样式
|
||||
const NAME = 'w-text-style'
|
||||
import api from '@/api'
|
||||
import _config from '@/config'
|
||||
// import api from '@/api'
|
||||
// import _config from '@/config'
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
import { styleIconList1, styleIconList2, alignIconList } from '../../../../assets/data/TextIconsData'
|
||||
import layerIconList from '@/assets/data/LayerIconList'
|
||||
@ -64,6 +64,7 @@ import textInputArea from '../../settings/textInputArea.vue'
|
||||
import valueSelect from '../../settings/valueSelect.vue'
|
||||
import effectWrap from '../../settings/EffectSelect/TextWrap.vue'
|
||||
import { useFontStore } from '@/common/methods/fonts'
|
||||
import usePageFontsFilter from './pageFontsFilter.ts'
|
||||
|
||||
export default {
|
||||
name: NAME,
|
||||
@ -124,11 +125,13 @@ export default {
|
||||
// if (!this.isDraw) {
|
||||
// useFontStore().init()
|
||||
const localFonts = useFontStore.list
|
||||
const fontLists = { 中文: [], 英文: [] }
|
||||
const fontLists = { 当前页面: [], 中文: [], 英文: [] }
|
||||
for (const font of localFonts) {
|
||||
const { id, value, url, alias, preview, lang } = font
|
||||
lang === 'zh' ? fontLists['中文'].unshift({ id, value, url, alias, preview }) : fontLists['英文'].unshift({ id, value, url, alias, preview })
|
||||
const { id, oid, value, url, alias, preview, lang } = font
|
||||
const item = { id, oid, value, url, alias, preview }
|
||||
lang === 'zh' ? fontLists['中文'].unshift(item) : fontLists['英文'].unshift(item)
|
||||
}
|
||||
fontLists['当前页面'] = usePageFontsFilter()
|
||||
this.fontClassList = fontLists
|
||||
// }
|
||||
// const isDev = process.env.NODE_ENV === 'development'
|
||||
@ -180,6 +183,9 @@ export default {
|
||||
value: value,
|
||||
pushHistory: false,
|
||||
})
|
||||
setTimeout(() => {
|
||||
key === 'fontClass' && (this.fontClassList['当前页面'] = usePageFontsFilter())
|
||||
}, 300)
|
||||
},
|
||||
layerAction(item) {
|
||||
this.updateLayerIndex({
|
||||
|
@ -18,4 +18,5 @@ export default {
|
||||
ICONFONT_URL: '//at.alicdn.com/t/font_2717063_ypy8vprc3b.css?display=swap',
|
||||
ICONFONT_EXTRA: '//at.alicdn.com/t/c/font_3228074_zubqmza1sdk.css',
|
||||
QINIUYUN_PLUGIN: 'https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/qiniu-js/2.5.5/qiniu.min.js',
|
||||
supportSubFont: true, // 是否开启服务端字体压缩
|
||||
}
|
||||
|
@ -1,29 +1,34 @@
|
||||
/*
|
||||
* @Author: ShawnPhang
|
||||
* @Date: 2023-08-23 17:37:16
|
||||
* @Description: 提取字体子集,如服务端不支持请关闭该功能,以保证页面能加载字体
|
||||
* @LastEditors: ShawnPhang <site: book.palxp.com>
|
||||
* @LastEditTime: 2023-08-23 17:48:34
|
||||
* @Description: 提取字体子集
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2023-10-14 18:31:29
|
||||
*/
|
||||
/**
|
||||
* 只有ttf/otf这种原始字体支持提取,如果服务端不支持该功能请设置false,以保证页面能加载字体。
|
||||
*/
|
||||
import _config from '@/config'
|
||||
export const fontWithDraw = _config.supportSubFont // true 开启,false 关闭
|
||||
|
||||
import api from '@/api'
|
||||
import { blob2Base64, generateFontStyle } from '@/common/methods/fonts/utils'
|
||||
|
||||
export const fontWithDraw = true // true开启,false关闭
|
||||
|
||||
export const font2style = async (fontContent: any, fontData: any = []) => {
|
||||
return new Promise((resolve: Function) => {
|
||||
Promise.all(
|
||||
// 提取字体子集。只有ttf/otf这种原始字体支持提取,如果服务端不支持则关闭该功能,以保证页面能加载字体。
|
||||
Object.keys(fontContent).map(async (key) => {
|
||||
const font = fontData.find((font: any) => font.value === key) as any
|
||||
if (font.id) {
|
||||
const extra = font.oid ? {} : { responseType: 'blob' }
|
||||
const params = {
|
||||
font_id: font.oid,
|
||||
id: font.id,
|
||||
content: shortText(fontContent[key]),
|
||||
}
|
||||
try {
|
||||
const base64 = await api.material.getFontSub({
|
||||
font_id: font.id,
|
||||
url: font.url,
|
||||
content: 'Aa' + fontContent[key],
|
||||
})
|
||||
fontContent[key] = base64
|
||||
const result = await api.material.getFontSub(params, extra)
|
||||
fontContent[key] = font.oid ? result : await blob2Base64(result)
|
||||
} catch (e) {
|
||||
console.log('字体获取失败', e)
|
||||
}
|
||||
@ -37,3 +42,9 @@ export const font2style = async (fontContent: any, fontData: any = []) => {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function shortText(text: string) {
|
||||
// 文字去重
|
||||
const textArr = Array.from(new Set(text.split('')))
|
||||
return textArr.join('')
|
||||
}
|
||||
|
@ -90,10 +90,6 @@ export default defineComponent({
|
||||
await preloadBg.imgs()
|
||||
}
|
||||
try {
|
||||
const { list } = await api.material.getFonts({ ids: fontData.map((x: any) => x.id) })
|
||||
fontData.forEach((item: any) => {
|
||||
item.url = list.find((x: any) => x.oid == item.id)?.ttf
|
||||
})
|
||||
fontWithDraw && (await font2style(fontContent, fontData))
|
||||
// console.log('1. base64 yes')
|
||||
const preload = new Preload(imgsData)
|
||||
|
@ -3,7 +3,7 @@
|
||||
* @Date: 2022-01-10 14:57:53
|
||||
* @Description: Psd文件解析
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2023-09-15 12:57:02
|
||||
* @LastEditTime: 2023-10-13 00:12:11
|
||||
-->
|
||||
<template>
|
||||
<div id="page-design-index" ref="pageDesignIndex">
|
||||
@ -56,7 +56,7 @@ import designBoard from '@/components/modules/layout/designBoard.vue'
|
||||
import zoomControl from '@/components/modules/layout/zoomControl.vue'
|
||||
import HeaderOptions from './components/UploadTemplate.vue'
|
||||
import ProgressLoading from '@/components/common/ProgressLoading/index.vue'
|
||||
import MyWorker from '@/utils/plugins/webWorker'
|
||||
// import MyWorker from '@/utils/plugins/webWorker'
|
||||
import { processPSD2Page } from '@/utils/plugins/psd'
|
||||
|
||||
export default defineComponent({
|
||||
|
Loading…
x
Reference in New Issue
Block a user