字体选择器增强 (#171)

* 字体选择器增强

* 优化字体选择器

---------

Co-authored-by: John Smith <xfgryujk@126.com>
This commit is contained in:
Sodako 2024-04-14 14:28:23 +08:00 committed by GitHub
parent 68fd680ec4
commit 47f47f2344
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 171 additions and 32 deletions

View File

@ -94,7 +94,10 @@ export default {
userNames: 'User Names',
showUserNames: 'Show user names',
font: 'Font',
fontSelectTip: 'You can also input local font name',
fontSelectTip: 'You can also input local font name. Fonts ranked first will be used first',
recentFonts: 'Recent fonts',
presetFonts: 'Preset fonts',
networkFonts: 'Network fonts',
fontSize: 'Font size',
lineHeight: 'Line height (0 for default)',
normalColor: 'Normal color',

View File

@ -94,7 +94,10 @@ export default {
userNames: 'ユーザー名',
showUserNames: 'ユーザー名を表示する',
font: 'フォント',
fontSelectTip: 'ローカルフォント名も入力することができます',
fontSelectTip: 'ローカルフォント名も入力することができます。最初にランク付けされたフォントが最初に使用されます',
recentFonts: '最近のフォント',
presetFonts: 'プリセットフォント',
networkFonts: 'ネットワークフォント',
fontSize: 'フォントサイズ',
lineHeight: '行の高さ0はデフォルト',
normalColor: 'ノーマルの色',

View File

@ -94,7 +94,10 @@ export default {
userNames: '用户名',
showUserNames: '显示用户名',
font: '字体',
fontSelectTip: '你也可以输入本地字体名',
fontSelectTip: '你也可以输入本地字体名。前面的字体会被优先使用',
recentFonts: '最近使用的字体',
presetFonts: '预设字体',
networkFonts: '网络字体',
fontSize: '字体尺寸',
lineHeight: '行高0为默认',
normalColor: '普通颜色',

View File

@ -1,10 +1,30 @@
<template>
<el-tooltip :content="$t('stylegen.fontSelectTip')">
<el-select :value="value" @input="val => $emit('input', val)" filterable allow-create default-first-option>
<el-option-group>
<el-option v-for="font in LOCAL_FONTS" :key="font" :value="font"></el-option>
<el-select :value="innerValue" @input="onInnerInput" @visible-change="updateRecentFonts"
multiple filterable allow-create default-first-option popper-class="font-select-popper" style="position: relative;"
>
<el-option-group
v-for="(groupCfg, index) in [
{ fonts: recentFonts, label: $t('stylegen.recentFonts'), isRecent: true },
{ fonts: PRESET_FONTS, label: $t('stylegen.presetFonts') },
]"
:key="index"
:label="groupCfg.label"
>
<el-option v-for="font in groupCfg.fonts" :key="font" :value="font">
<span class="fonts-select-name-line">
<span>{{ font }}</span>
<el-button v-if="groupCfg.isRecent" type="text" class="fonts-select-btn" style="color: #f56c6c;"
@click="() => deleteRecentFont(font)"
>
<i class="el-icon-delete"></i>
</el-button>
</span>
<span class="fonts-select-sample" :style="{'font-family': font}">Sample 样例 サンプル</span>
</el-option>
</el-option-group>
<el-option-group>
<el-option-group :label="$t('stylegen.networkFonts')">
<el-option v-for="font in NETWORK_FONTS" :key="font" :value="font"></el-option>
</el-option-group>
</el-select>
@ -12,6 +32,7 @@
</template>
<script>
import * as common from './common'
import * as fonts from './fonts'
export default {
@ -21,8 +42,61 @@ export default {
},
data() {
return {
LOCAL_FONTS: fonts.LOCAL_FONTS,
NETWORK_FONTS: fonts.NETWORK_FONTS
recentFonts: this.getRecentFonts(), // localStorage
PRESET_FONTS: fonts.PRESET_FONTS,
NETWORK_FONTS: fonts.NETWORK_FONTS,
innerValue: [],
}
},
watch: {
value: {
immediate: true,
handler(val) {
this.innerValue = common.fontsStrToArr(val)
}
}
},
methods: {
onInnerInput(val) {
let addedFonts = val.filter(font => this.innerValue.indexOf(font) === -1)
this.innerValue = val
this.$emit('input', common.fontsArrToStr(this.innerValue))
for (let font of addedFonts) {
this.addRecentFont(font)
}
},
updateRecentFonts() {
this.recentFonts = this.getRecentFonts()
},
getRecentFonts() {
return common.fontsStrToArr(window.localStorage.recentFonts || '')
},
setRecentFonts(recentFonts) {
window.localStorage.recentFonts = common.fontsArrToStr(recentFonts)
},
addRecentFont(font) {
let recentFonts = this.getRecentFonts()
let index = recentFonts.indexOf(font)
if (index !== -1) {
recentFonts.splice(index, 1)
}
recentFonts.unshift(font)
this.setRecentFonts(recentFonts)
this.updateRecentFonts()
},
deleteRecentFont(font) {
let recentFonts = this.getRecentFonts()
let index = recentFonts.indexOf(font)
if (index !== -1) {
recentFonts.splice(index, 1)
this.setRecentFonts(recentFonts)
}
this.updateRecentFonts()
}
}
}
@ -30,6 +104,36 @@ export default {
<style scoped>
.el-select {
width: 100%
width: 100%;
}
.font-select-popper .el-select-group .el-select-dropdown__item {
display: flex;
flex-direction: column;
padding: 8px 20px;
height: fit-content;
}
.fonts-select-name-line {
display: flex;
justify-content: space-between;
align-items: center;
line-height: 1.5em;
}
.fonts-select-btn {
opacity: 0.2;
transition: 0.5s;
padding: 0 0 0 8px;
margin-right: 20px;
}
.fonts-select-btn:hover {
opacity: 1;
}
.fonts-select-sample {
opacity: 0.4;
line-height: 1.5em;
}
</style>

View File

@ -485,7 +485,7 @@ yt-live-chat-text-message-renderer {
return `/* Outlines */
yt-live-chat-renderer * {
${this.showOutlinesStyle}
font-family: "${common.cssEscapeStr(this.form.messageFont)}"${common.FALLBACK_FONTS};
font-family: ${common.fontsStrToCss(this.form.messageFont)};
font-size: ${this.form.messageFontSize}px !important;
line-height: ${this.form.messageLineHeight || this.form.messageFontSize}px !important;
}`
@ -525,7 +525,7 @@ yt-live-chat-text-message-renderer yt-live-chat-author-badge-renderer[type="memb
yt-live-chat-text-message-renderer #author-name {
${this.form.showUserNames ? '' : 'display: none !important;'}
${this.form.userNameColor ? `color: ${this.form.userNameColor} !important;` : ''}
font-family: "${common.cssEscapeStr(this.form.userNameFont)}"${common.FALLBACK_FONTS};
font-family: ${common.fontsStrToCss(this.form.userNameFont)};
font-size: ${this.form.userNameFontSize}px !important;
line-height: ${this.form.userNameLineHeight || this.form.userNameFontSize}px !important;
}
@ -547,7 +547,7 @@ yt-live-chat-text-message-renderer #chat-badges {
yt-live-chat-text-message-renderer #message,
yt-live-chat-text-message-renderer #message * {
${this.form.messageColor ? `color: ${this.form.messageColor} !important;` : ''}
font-family: "${common.cssEscapeStr(this.form.messageFont)}"${common.FALLBACK_FONTS};
font-family: ${common.fontsStrToCss(this.form.messageFont)};
font-size: ${this.form.messageFontSize}px !important;
line-height: ${this.form.messageLineHeight || this.form.messageFontSize}px !important;
}
@ -609,7 +609,7 @@ yt-live-chat-paid-message-renderer #author-name *,
yt-live-chat-membership-item-renderer #header-content-inner-column,
yt-live-chat-membership-item-renderer #header-content-inner-column * {
${this.form.firstLineColor ? `color: ${this.form.firstLineColor} !important;` : ''}
font-family: "${common.cssEscapeStr(this.form.firstLineFont)}"${common.FALLBACK_FONTS};
font-family: ${common.fontsStrToCss(this.form.firstLineFont)};
font-size: ${this.form.firstLineFontSize}px !important;
line-height: ${this.form.firstLineLineHeight || this.form.firstLineFontSize}px !important;
}
@ -619,7 +619,7 @@ yt-live-chat-paid-message-renderer #purchase-amount *,
yt-live-chat-membership-item-renderer #header-subtext,
yt-live-chat-membership-item-renderer #header-subtext * {
${this.form.secondLineColor ? `color: ${this.form.secondLineColor} !important;` : ''}
font-family: "${common.cssEscapeStr(this.form.secondLineFont)}"${common.FALLBACK_FONTS};
font-family: ${common.fontsStrToCss(this.form.secondLineFont)};
font-size: ${this.form.secondLineFontSize}px !important;
line-height: ${this.form.secondLineLineHeight || this.form.secondLineFontSize}px !important;
}
@ -627,7 +627,7 @@ yt-live-chat-membership-item-renderer #header-subtext * {
yt-live-chat-paid-message-renderer #content,
yt-live-chat-paid-message-renderer #content * {
${this.form.scContentColor ? `color: ${this.form.scContentColor} !important;` : ''}
font-family: "${common.cssEscapeStr(this.form.scContentFont)}"${common.FALLBACK_FONTS};
font-family: ${common.fontsStrToCss(this.form.scContentFont)};
font-size: ${this.form.scContentFontSize}px !important;
line-height: ${this.form.scContentLineHeight || this.form.scContentFontSize}px !important;
}`
@ -653,7 +653,7 @@ yt-live-chat-ticker-paid-message-item-renderer *,
yt-live-chat-ticker-sponsor-item-renderer,
yt-live-chat-ticker-sponsor-item-renderer * {
${this.form.secondLineColor ? `color: ${this.form.secondLineColor} !important;` : ''}
font-family: "${common.cssEscapeStr(this.form.secondLineFont)}"${common.FALLBACK_FONTS};
font-family: ${common.fontsStrToCss(this.form.secondLineFont)};
}`
},
animationStyle() {
@ -666,7 +666,7 @@ yt-live-chat-ticker-sponsor-item-renderer * {
this.saveConfig()
}
},
created() {
mounted() {
this.$emit('input', this.result)
},
methods: {

View File

@ -451,7 +451,7 @@ yt-live-chat-text-message-renderer yt-live-chat-author-badge-renderer[type="memb
yt-live-chat-text-message-renderer #author-name {
${this.form.showUserNames ? '' : 'display: none !important;'}
${this.form.userNameColor ? `color: ${this.form.userNameColor} !important;` : ''}
font-family: "${common.cssEscapeStr(this.form.userNameFont)}"${common.FALLBACK_FONTS};
font-family: ${common.fontsStrToCss(this.form.userNameFont)};
font-size: ${this.form.userNameFontSize}px !important;
line-height: ${this.form.userNameLineHeight || (this.form.userNameFontSize + 2)}px !important;
}
@ -467,7 +467,7 @@ yt-live-chat-text-message-renderer #chat-badges {
yt-live-chat-text-message-renderer #message,
yt-live-chat-text-message-renderer #message * {
${this.form.messageColor ? `color: ${this.form.messageColor} !important;` : ''}
font-family: "${common.cssEscapeStr(this.form.messageFont)}"${common.FALLBACK_FONTS};
font-family: ${common.fontsStrToCss(this.form.messageFont)};
font-size: ${this.form.messageFontSize}px !important;
line-height: ${this.form.messageLineHeight || (this.form.messageFontSize + 2)}px !important;
}
@ -556,7 +556,7 @@ ${this.form.showOtherThings ? '' : `yt-live-chat-item-list-renderer {
yt-live-chat-paid-message-renderer #author-name *,
yt-live-chat-membership-item-renderer #header-content-inner-column,
yt-live-chat-membership-item-renderer #header-content-inner-column * {
font-family: "${common.cssEscapeStr(this.form.firstLineFont)}"${common.FALLBACK_FONTS};
font-family: ${common.fontsStrToCss(this.form.firstLineFont)};
font-size: ${this.form.firstLineFontSize}px !important;
line-height: ${this.form.firstLineLineHeight || (this.form.firstLineFontSize + 2)}px !important;
}
@ -565,14 +565,14 @@ yt-live-chat-paid-message-renderer #purchase-amount,
yt-live-chat-paid-message-renderer #purchase-amount *,
yt-live-chat-membership-item-renderer #header-subtext,
yt-live-chat-membership-item-renderer #header-subtext * {
font-family: "${common.cssEscapeStr(this.form.secondLineFont)}"${common.FALLBACK_FONTS};
font-family: ${common.fontsStrToCss(this.form.secondLineFont)};
font-size: ${this.form.secondLineFontSize}px !important;
line-height: ${this.form.secondLineLineHeight || (this.form.secondLineFontSize + 2)}px !important;
}
yt-live-chat-paid-message-renderer #content,
yt-live-chat-paid-message-renderer #content * {
font-family: "${common.cssEscapeStr(this.form.scContentFont)}"${common.FALLBACK_FONTS};
font-family: ${common.fontsStrToCss(this.form.scContentFont)};
font-size: ${this.form.scContentFontSize}px !important;
line-height: ${this.form.scContentLineHeight || (this.form.scContentFontSize + 2)}px !important;
}`
@ -591,7 +591,7 @@ yt-live-chat-ticker-paid-message-item-renderer,
yt-live-chat-ticker-paid-message-item-renderer *,
yt-live-chat-ticker-sponsor-item-renderer,
yt-live-chat-ticker-sponsor-item-renderer * {
font-family: "${common.cssEscapeStr(this.form.secondLineFont)}"${common.FALLBACK_FONTS};
font-family: ${common.fontsStrToCss(this.form.secondLineFont)};
}`
},
animationStyle() {
@ -604,7 +604,7 @@ yt-live-chat-ticker-sponsor-item-renderer * {
this.saveConfig()
}
},
created() {
mounted() {
this.$emit('input', this.result)
},
methods: {

View File

@ -1,6 +1,7 @@
import * as fonts from './fonts'
export const FALLBACK_FONTS = ', "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "\\5FAE \\8F6F \\96C5 \\9ED1 ", SimHei, Arial, sans-serif'
const FALLBACK_FONTS_CSS = '"Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", \
"\\5FAE \\8F6F \\96C5 \\9ED1 ", SimHei, Arial, sans-serif'
export const COMMON_STYLE = `/* Transparent background */
yt-live-chat-renderer {
@ -53,7 +54,14 @@ yt-live-chat-membership-item-renderer a {
text-decoration: none !important;
}`
export function getImportStyle(allFonts) {
export function getImportStyle(allFontsStrs) {
let allFonts = new Set()
for (let fontsStr of allFontsStrs) {
for (let font of fontsStrToArr(fontsStr)) {
allFonts.add(font)
}
}
let fontsNeedToImport = new Set()
for (let font of allFonts) {
if (fonts.NETWORK_FONTS.indexOf(font) !== -1) {
@ -88,7 +96,7 @@ export function getTimeStyle(config) {
yt-live-chat-text-message-renderer #timestamp {
display: ${config.showTime ? 'inline' : 'none'} !important;
${config.timeColor ? `color: ${config.timeColor} !important;` : ''}
font-family: "${cssEscapeStr(config.timeFont)}"${FALLBACK_FONTS};
font-family: ${fontsStrToCss(config.timeFont)};
font-size: ${config.timeFontSize}px !important;
line-height: ${config.timeLineHeight || config.timeFontSize}px !important;
}`
@ -136,12 +144,30 @@ yt-live-chat-paid-message-renderer {
}`
}
export function cssEscapeStr(str) {
export function fontsStrToArr(fontsStr) {
return fontsStr ? fontsStr.split(',') : []
}
export function fontsArrToStr(fontsArr) {
return fontsArr.join(',')
}
export function fontsStrToCss(fontsStr) {
let fontsArr = fontsStrToArr(fontsStr)
if (fontsArr.length === 0) {
return FALLBACK_FONTS_CSS
}
fontsArr = fontsArr.map(cssEscapeStr)
fontsArr.push(FALLBACK_FONTS_CSS)
return fontsArr.join(', ')
}
function cssEscapeStr(str) {
let res = []
for (let char of str) {
res.push(cssEscapeChar(char))
}
return res.join('')
return `"${res.join('')}"`
}
function cssEscapeChar(char) {

File diff suppressed because one or more lines are too long