mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-04-11 15:47:06 +08:00
refactor: 字体类
This commit is contained in:
parent
4c898a7836
commit
ee5b962743
@ -1,5 +1,6 @@
|
||||
export * from './preset';
|
||||
export * from './renderer';
|
||||
export * from './style';
|
||||
export * from './adapter';
|
||||
export * from './cache';
|
||||
export * from './camera';
|
||||
|
@ -6,6 +6,7 @@ import { texture } from '../cache';
|
||||
import { isNil } from 'lodash-es';
|
||||
import { logger } from '@/core/common/logger';
|
||||
import { IAnimateFrame, renderEmits } from '../frame';
|
||||
import { Font } from '../style/font';
|
||||
|
||||
/** 文字的安全填充,会填充在文字的上侧和下侧,防止削顶和削底 */
|
||||
const SAFE_PAD = 1;
|
||||
@ -21,7 +22,7 @@ export class Text extends RenderItem<ETextEvent> {
|
||||
|
||||
fillStyle?: CanvasStyle = '#fff';
|
||||
strokeStyle?: CanvasStyle;
|
||||
font: string = '16px Verdana';
|
||||
font: Font = new Font();
|
||||
strokeWidth: number = 1;
|
||||
|
||||
private length: number = 0;
|
||||
@ -50,7 +51,7 @@ export class Text extends RenderItem<ETextEvent> {
|
||||
ctx.textBaseline = 'bottom';
|
||||
ctx.fillStyle = this.fillStyle ?? 'transparent';
|
||||
ctx.strokeStyle = this.strokeStyle ?? 'transparent';
|
||||
ctx.font = this.font;
|
||||
ctx.font = this.font.string();
|
||||
ctx.lineWidth = this.strokeWidth;
|
||||
|
||||
if (this.strokeStyle) {
|
||||
@ -67,7 +68,7 @@ export class Text extends RenderItem<ETextEvent> {
|
||||
measure() {
|
||||
const ctx = Text.measureCanvas.ctx;
|
||||
ctx.textBaseline = 'bottom';
|
||||
ctx.font = this.font;
|
||||
ctx.font = this.font.string();
|
||||
const res = ctx.measureText(this.text);
|
||||
return res;
|
||||
}
|
||||
@ -87,7 +88,7 @@ export class Text extends RenderItem<ETextEvent> {
|
||||
* 设置使用的字体
|
||||
* @param font 字体
|
||||
*/
|
||||
setFont(font: string) {
|
||||
setFont(font: Font) {
|
||||
this.font = font;
|
||||
this.calBox();
|
||||
this.update(this);
|
||||
@ -145,7 +146,7 @@ export class Text extends RenderItem<ETextEvent> {
|
||||
this.setStyle(this.fillStyle, nextValue);
|
||||
return true;
|
||||
case 'font':
|
||||
if (!this.assertType(nextValue, 'string', key)) return false;
|
||||
if (!this.assertType(nextValue, Font, key)) return false;
|
||||
this.setFont(nextValue);
|
||||
return true;
|
||||
case 'strokeWidth':
|
||||
|
@ -18,6 +18,7 @@ import {
|
||||
} from '../preset/graphics';
|
||||
import { ElementAnchor, ElementLocator, ElementScale } from '../utils';
|
||||
import { CustomContainerRenderFn } from '../container';
|
||||
import { Font } from '../style/font';
|
||||
|
||||
export interface CustomProps {
|
||||
_item: (props: BaseProps) => RenderItem;
|
||||
@ -100,7 +101,7 @@ export interface TextProps extends BaseProps {
|
||||
text?: string;
|
||||
fillStyle?: CanvasStyle;
|
||||
strokeStyle?: CanvasStyle;
|
||||
font?: string;
|
||||
font?: Font;
|
||||
strokeWidth?: number;
|
||||
}
|
||||
|
||||
|
155
src/core/render/style/font.ts
Normal file
155
src/core/render/style/font.ts
Normal file
@ -0,0 +1,155 @@
|
||||
import { logger } from '@/core/common/logger';
|
||||
|
||||
export interface IFontConfig {
|
||||
/** 字体类型 */
|
||||
readonly family: string;
|
||||
/** 字体大小的值 */
|
||||
readonly size: number;
|
||||
/** 字体大小单位,推荐使用 px */
|
||||
readonly sizeUnit: string;
|
||||
/** 字体粗细,范围 0-1000 */
|
||||
readonly weight: number;
|
||||
/** 是否斜体 */
|
||||
readonly italic: boolean;
|
||||
}
|
||||
|
||||
export const enum FontWeight {
|
||||
Light = 300,
|
||||
Normal = 400,
|
||||
Bold = 700
|
||||
}
|
||||
|
||||
type _FontStretch =
|
||||
| 'ultra-condensed'
|
||||
| 'extra-condensed'
|
||||
| 'condensed'
|
||||
| 'semi-condensed'
|
||||
| 'normal'
|
||||
| 'semi-expanded'
|
||||
| 'expanded'
|
||||
| 'extra-expanded'
|
||||
| 'ultra-expanded';
|
||||
|
||||
type _FontVariant = 'normal' | 'small-caps';
|
||||
|
||||
export class Font implements IFontConfig {
|
||||
private readonly fallbacks: Font[] = [];
|
||||
|
||||
private fontString: string = '';
|
||||
|
||||
constructor(
|
||||
public readonly family: string = 'Verdana',
|
||||
public readonly size: number = 16,
|
||||
public readonly sizeUnit: string = 'px',
|
||||
public readonly weight: number = 400,
|
||||
public readonly italic: boolean = false
|
||||
) {
|
||||
this.fontString = this.getFont();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加补充字体,若当前字体不可用,那么会使用补充字体,补充字体也可以添加补充字体,但是请避免递归添加
|
||||
* @param fallback 补充字体
|
||||
*/
|
||||
addFallback(...fallback: Font[]) {
|
||||
this.fallbacks.push(...fallback);
|
||||
this.fontString = this.getFont();
|
||||
}
|
||||
|
||||
private build() {
|
||||
return `${
|
||||
this.italic ? 'italic ' : ''
|
||||
} ${this.weight} ${this.size}${this.sizeUnit} ${this.family}`;
|
||||
}
|
||||
|
||||
private getFallbackFont(used: Set<Font>) {
|
||||
let font = '';
|
||||
this.fallbacks.forEach(v => {
|
||||
if (used.has(v)) {
|
||||
logger.warn(62, this.build());
|
||||
return;
|
||||
}
|
||||
used.add(v);
|
||||
font += `, ${v.getFallbackFont(used)}`;
|
||||
});
|
||||
return font;
|
||||
}
|
||||
|
||||
private getFont() {
|
||||
if (this.fallbacks.length === 0) {
|
||||
return this.build();
|
||||
} else {
|
||||
const usedFont = new Set<Font>();
|
||||
return this.build() + this.getFallbackFont(usedFont);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字体的 CSS 字符串
|
||||
*/
|
||||
string() {
|
||||
return this.fontString;
|
||||
}
|
||||
|
||||
private static parseOne(str: string) {
|
||||
if (!str) return new Font();
|
||||
let italic = false;
|
||||
let weight = 400;
|
||||
let size = 16;
|
||||
let unit = 'px';
|
||||
let family = 'Verdana';
|
||||
const tokens = str.split(/\s+/);
|
||||
tokens.forEach(v => {
|
||||
// font-italic
|
||||
if (v === 'italic') {
|
||||
italic = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// font-weight
|
||||
const num = Number(v);
|
||||
if (!isNaN(num)) {
|
||||
weight = num;
|
||||
return;
|
||||
}
|
||||
|
||||
// font-size
|
||||
const parse = parseFloat(v);
|
||||
if (!isNaN(parse)) {
|
||||
size = parse;
|
||||
unit = v.slice(parse.toString().length);
|
||||
return;
|
||||
}
|
||||
});
|
||||
family = tokens.at(-1) ?? 'Verdana';
|
||||
return new Font(family, size, unit, weight, italic);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 CSS 字体字符串解析出 Font 实例,不支持的属性将被忽略
|
||||
*/
|
||||
static parse(str: string) {
|
||||
const fonts = str.split(',');
|
||||
const main = this.parseOne(fonts[0]);
|
||||
for (let i = 1; i < fonts.length; i++) {
|
||||
main.addFallback(this.parseOne(fonts[i]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制一个字体,同时修改字体的一部分属性
|
||||
* @param font 要复制的字体
|
||||
*/
|
||||
static clone(
|
||||
font: Font,
|
||||
{
|
||||
family = font.family,
|
||||
size = font.size,
|
||||
sizeUnit = font.sizeUnit,
|
||||
weight = font.weight,
|
||||
italic = font.italic
|
||||
}: Partial<IFontConfig>
|
||||
) {
|
||||
return new Font(family, size, sizeUnit, weight, italic);
|
||||
}
|
||||
}
|
1
src/core/render/style/index.ts
Normal file
1
src/core/render/style/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './font';
|
@ -92,7 +92,8 @@
|
||||
"58": "Fail to set ellipse round rect, since length of 'ellipse' property should only be 2, 4, 6 or 8. delivered: $1",
|
||||
"59": "Unknown icon '$1' in parsing text content.",
|
||||
"60": "Repeated Tip id: '$1'.",
|
||||
"61": "Unexpected recursive call of $1.update in render function. Please ensure you must do this, if you do, ignore this warn.",
|
||||
"61": "Unexpected recursive call of $1.update in render function. Please ensure you have to do this, if you do, ignore this warn.",
|
||||
"62": "Recursive fallback fonts in '$1'.",
|
||||
"1001": "Item-detail extension needs 'floor-binder' and 'floor-damage' extension as dependency.",
|
||||
"1101": "Cannot add new effect to point effect instance, for there's no more reserve space for it. Please increase the max count of the instance."
|
||||
}
|
||||
|
@ -1,3 +1,9 @@
|
||||
export * from './choices';
|
||||
export * from './icons';
|
||||
export * from './misc';
|
||||
export * from './page';
|
||||
export * from './scroll';
|
||||
export * from './textbox';
|
||||
export * from './textboxTyper';
|
||||
export * from './tip';
|
||||
export * from './types';
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
} from 'vue';
|
||||
import { SetupComponentOptions } from './types';
|
||||
import { clamp } from 'lodash-es';
|
||||
import { DefaultProps, ElementLocator } from '@/core/render';
|
||||
import { DefaultProps, ElementLocator, Font } from '@/core/render';
|
||||
|
||||
/** 圆角矩形页码距离容器的边框大小,与 pageSize 相乘 */
|
||||
const RECT_PAD = 0.1;
|
||||
@ -20,8 +20,10 @@ export interface PageProps extends DefaultProps {
|
||||
pages: number;
|
||||
/** 页码组件的定位 */
|
||||
loc: ElementLocator;
|
||||
/** 页码的字体大小,默认为 14 */
|
||||
pageSize?: number;
|
||||
/** 页码的字体 */
|
||||
font?: Font;
|
||||
/** 只有一页的时候,是否隐藏页码 */
|
||||
hideIfSingle?: boolean;
|
||||
}
|
||||
|
||||
export interface PageExpose {
|
||||
@ -37,7 +39,7 @@ type PageSlots = SlotsType<{
|
||||
}>;
|
||||
|
||||
const pageProps = {
|
||||
props: ['pages', 'loc', 'pageSize']
|
||||
props: ['pages', 'loc', 'font', 'hideIfSingle']
|
||||
} satisfies SetupComponentOptions<PageProps, {}, string, PageSlots>;
|
||||
|
||||
/**
|
||||
@ -80,14 +82,15 @@ export const Page = defineComponent<PageProps, {}, string, PageSlots>(
|
||||
const leftArrow = ref<Path2D>();
|
||||
const rightArrow = ref<Path2D>();
|
||||
|
||||
const font = computed(() => props.font ?? new Font());
|
||||
const isFirst = computed(() => nowPage.value === 1);
|
||||
const isLast = computed(() => nowPage.value === props.pages);
|
||||
const pageSize = computed(() => props.pageSize ?? 14);
|
||||
const width = computed(() => props.loc[2] ?? 200);
|
||||
const height = computed(() => props.loc[3] ?? 200);
|
||||
const round = computed(() => pageSize.value / 4);
|
||||
const pageFont = computed(() => `${pageSize.value}px normal`);
|
||||
const nowPageFont = computed(() => `bold ${pageSize.value}px normal`);
|
||||
const round = computed(() => font.value.size / 4);
|
||||
const nowPageFont = computed(() =>
|
||||
Font.clone(font.value, { weight: 700 })
|
||||
);
|
||||
|
||||
// 左右箭头的颜色
|
||||
const leftColor = computed(() => (isFirst.value ? '#666' : '#ddd'));
|
||||
@ -100,11 +103,11 @@ export const Page = defineComponent<PageProps, {}, string, PageSlots>(
|
||||
nextTick(() => {
|
||||
updating = false;
|
||||
});
|
||||
const pageH = pageSize.value + 8;
|
||||
const pageH = font.value.size + 8;
|
||||
contentLoc.value = [0, 0, width.value, height.value - pageH];
|
||||
pageLoc.value = [0, height.value - pageH, width.value, pageH];
|
||||
const center = width.value / 2;
|
||||
const size = pageSize.value * 1.5;
|
||||
const size = font.value.size * 1.5;
|
||||
nowPageLoc.value = [center, 0, size, size, 0.5, 0];
|
||||
leftPageLoc.value = [center - size * 1.5, 0, size, size, 0.5, 0];
|
||||
leftLoc.value = [center - size * 3, 0, size, size, 0.5, 0];
|
||||
@ -113,8 +116,8 @@ export const Page = defineComponent<PageProps, {}, string, PageSlots>(
|
||||
};
|
||||
|
||||
const updateArrowPath = () => {
|
||||
const rectSize = pageSize.value * 1.5;
|
||||
const size = pageSize.value;
|
||||
const rectSize = font.value.size * 1.5;
|
||||
const size = font.value.size;
|
||||
const pad = rectSize - size;
|
||||
const left = new Path2D();
|
||||
left.moveTo(size, pad);
|
||||
@ -129,13 +132,13 @@ export const Page = defineComponent<PageProps, {}, string, PageSlots>(
|
||||
};
|
||||
|
||||
const updateRectAndText = () => {
|
||||
const size = pageSize.value * 1.5;
|
||||
const size = font.value.size * 1.5;
|
||||
const pad = RECT_PAD * size;
|
||||
rectLoc.value = [pad, pad, size - pad * 2, size - pad * 2];
|
||||
textLoc.value = [size / 2, size / 2, void 0, void 0, 0.5, 0.5];
|
||||
};
|
||||
|
||||
watch(pageSize, () => {
|
||||
watch(font, () => {
|
||||
updatePagePos();
|
||||
updateArrowPath();
|
||||
updateRectAndText();
|
||||
@ -178,7 +181,10 @@ export const Page = defineComponent<PageProps, {}, string, PageSlots>(
|
||||
<container loc={contentLoc.value}>
|
||||
{slots.default?.(nowPage.value)}
|
||||
</container>
|
||||
<container loc={pageLoc.value}>
|
||||
<container
|
||||
loc={pageLoc.value}
|
||||
hidden={props.hideIfSingle && props.pages === 1}
|
||||
>
|
||||
<container
|
||||
loc={leftLoc.value}
|
||||
onClick={lastPage}
|
||||
@ -214,7 +220,7 @@ export const Page = defineComponent<PageProps, {}, string, PageSlots>(
|
||||
<text
|
||||
loc={textLoc.value}
|
||||
text={(nowPage.value - 1).toString()}
|
||||
font={pageFont.value}
|
||||
font={font.value}
|
||||
></text>
|
||||
</container>
|
||||
)}
|
||||
@ -251,7 +257,7 @@ export const Page = defineComponent<PageProps, {}, string, PageSlots>(
|
||||
<text
|
||||
loc={textLoc.value}
|
||||
text={(nowPage.value + 1).toString()}
|
||||
font={pageFont.value}
|
||||
font={font.value}
|
||||
></text>
|
||||
</container>
|
||||
)}
|
||||
|
@ -27,7 +27,7 @@ import {
|
||||
WordBreak,
|
||||
TextAlign
|
||||
} from './textboxTyper';
|
||||
import { ElementLocator } from '@/core/render';
|
||||
import { ElementLocator, Font } from '@/core/render';
|
||||
|
||||
export interface TextContentProps
|
||||
extends DefaultProps,
|
||||
@ -70,10 +70,7 @@ export interface TextContentExpose {
|
||||
const textContentOptions = {
|
||||
props: [
|
||||
'breakChars',
|
||||
'fontFamily',
|
||||
'fontSize',
|
||||
'fontWeight',
|
||||
'fontItalic',
|
||||
'font',
|
||||
'ignoreLineEnd',
|
||||
'ignoreLineStart',
|
||||
'interval',
|
||||
@ -225,7 +222,7 @@ export interface TextboxProps extends TextContentProps, DefaultProps {
|
||||
/** 标题 */
|
||||
title?: string;
|
||||
/** 标题字体 */
|
||||
titleFont?: string;
|
||||
titleFont?: Font;
|
||||
/** 标题填充样式 */
|
||||
titleFill?: CanvasStyle;
|
||||
/** 标题描边样式 */
|
||||
@ -296,10 +293,7 @@ export const Textbox = defineComponent<
|
||||
|
||||
const setContentData = () => {
|
||||
contentData.breakChars = props.breakChars ?? '';
|
||||
contentData.fontFamily = props.fontFamily ?? 'Verdana';
|
||||
contentData.fontSize = props.fontSize ?? 16;
|
||||
contentData.fontWeight = props.fontWeight ?? 500;
|
||||
contentData.fontItalic = props.fontItalic ?? false;
|
||||
contentData.font = props.font ?? new Font();
|
||||
contentData.ignoreLineEnd = props.ignoreLineEnd ?? '';
|
||||
contentData.ignoreLineStart = props.ignoreLineStart ?? '';
|
||||
contentData.interval = props.interval ?? 0;
|
||||
@ -323,7 +317,7 @@ export const Textbox = defineComponent<
|
||||
data.padding = props.padding ?? 8;
|
||||
data.titleFill = props.titleFill ?? 'gold';
|
||||
data.titleStroke = props.titleStroke ?? 'transparent';
|
||||
data.titleFont = props.titleFont ?? '18px Verdana';
|
||||
data.titleFont = props.titleFont ?? new Font('Verdana', 18);
|
||||
data.titlePadding = props.titlePadding ?? 8;
|
||||
data.width = props.width ?? props.loc?.[2] ?? 200;
|
||||
data.height = props.height ?? props.loc?.[3] ?? 200;
|
||||
|
@ -2,6 +2,7 @@ import { logger } from '@/core/common/logger';
|
||||
import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d';
|
||||
import {
|
||||
AutotileRenderable,
|
||||
Font,
|
||||
onTick,
|
||||
RenderableData,
|
||||
texture
|
||||
@ -28,14 +29,8 @@ export const enum TextAlign {
|
||||
}
|
||||
|
||||
export interface ITextContentConfig {
|
||||
/** 字体类型 */
|
||||
fontFamily: string;
|
||||
/** 字体大小 */
|
||||
fontSize: number;
|
||||
/** 字体线宽 */
|
||||
fontWeight: number;
|
||||
/** 是否斜体 */
|
||||
fontItalic: boolean;
|
||||
/** 字体 */
|
||||
font: Font;
|
||||
/** 是否持续上一次的文本,开启后,如果修改后的文本以修改前的文本为开头,那么会继续播放而不会从头播放 */
|
||||
keepLast: boolean;
|
||||
/** 打字机时间间隔,即两个字出现之间相隔多长时间 */
|
||||
@ -62,6 +57,17 @@ export interface ITextContentConfig {
|
||||
width: number;
|
||||
}
|
||||
|
||||
interface TyperConfig extends ITextContentConfig {
|
||||
/** 字体类型 */
|
||||
fontFamily: string;
|
||||
/** 字体大小 */
|
||||
fontSize: number;
|
||||
/** 字体线宽 */
|
||||
fontWeight: number;
|
||||
/** 是否斜体 */
|
||||
fontItalic: boolean;
|
||||
}
|
||||
|
||||
export interface ITextContentRenderData {
|
||||
text: string;
|
||||
title?: string;
|
||||
@ -162,7 +168,7 @@ type TyperFunction = (data: TyperRenderable[], typing: boolean) => void;
|
||||
|
||||
export class TextContentTyper extends EventEmitter<TextContentTyperEvent> {
|
||||
/** 文字配置信息 */
|
||||
readonly config: Required<ITextContentConfig>;
|
||||
readonly config: Required<TyperConfig>;
|
||||
/** 文字解析器 */
|
||||
readonly parser: TextContentParser;
|
||||
|
||||
@ -205,12 +211,14 @@ export class TextContentTyper extends EventEmitter<TextContentTyperEvent> {
|
||||
|
||||
constructor(config: Partial<ITextContentConfig>) {
|
||||
super();
|
||||
const font = config.font ?? new Font();
|
||||
|
||||
this.config = {
|
||||
fontFamily: config.fontFamily ?? 'Verdana',
|
||||
fontSize: config.fontSize ?? 16,
|
||||
fontWeight: config.fontWeight ?? 500,
|
||||
fontItalic: config.fontItalic ?? false,
|
||||
font,
|
||||
fontFamily: font.family,
|
||||
fontSize: font.size,
|
||||
fontWeight: font.weight,
|
||||
fontItalic: font.italic,
|
||||
keepLast: config.keepLast ?? false,
|
||||
interval: config.interval ?? 0,
|
||||
lineHeight: config.lineHeight ?? 0,
|
||||
@ -762,7 +770,7 @@ export class TextContentParser {
|
||||
|
||||
private parseFontWeight() {
|
||||
if (this.resolved.length > 0) this.addTextRenderable();
|
||||
this.status.fontWeight = this.status.fontWeight > 500 ? 500 : 700;
|
||||
this.status.fontWeight = this.status.fontWeight > 400 ? 400 : 700;
|
||||
this.font = this.buildFont();
|
||||
}
|
||||
|
||||
@ -1300,7 +1308,7 @@ function isCJK(char: number) {
|
||||
export function buildFont(
|
||||
family: string,
|
||||
size: number,
|
||||
weight: number = 500,
|
||||
weight: number = 400,
|
||||
italic: boolean = false
|
||||
) {
|
||||
return `${italic ? 'italic ' : ''}${weight} ${size}px "${family}"`;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { DefaultProps, ElementLocator, texture } from '@/core/render';
|
||||
import { DefaultProps, ElementLocator, Font, texture } from '@/core/render';
|
||||
import { computed, defineComponent, onUnmounted, ref } from 'vue';
|
||||
import { SetupComponentOptions } from './types';
|
||||
import { transitioned } from '../use';
|
||||
@ -36,7 +36,7 @@ export const Tip = defineComponent<TipProps>((props, { expose }) => {
|
||||
const text = ref<string>('');
|
||||
const textWidth = ref(0);
|
||||
|
||||
const font = '16px normal';
|
||||
const font = new Font('normal');
|
||||
|
||||
const alpha = transitioned(0, 500, hyper('sin', 'in-out'))!;
|
||||
const pad = computed(() => props.pad ?? [4, 4]);
|
||||
|
@ -8,7 +8,8 @@ import {
|
||||
HeroRenderer,
|
||||
LayerDoorAnimate,
|
||||
Props,
|
||||
LayerGroup
|
||||
LayerGroup,
|
||||
Font
|
||||
} from '@/core/render';
|
||||
import { WeatherController } from '@/module/weather';
|
||||
import { FloorChange } from '@/plugin/fallback';
|
||||
@ -62,8 +63,8 @@ const MainScene = defineComponent(() => {
|
||||
zIndex: 30,
|
||||
fillStyle: '#fff',
|
||||
titleFill: 'gold',
|
||||
fontFamily: 'normal',
|
||||
titleFont: '700 20px normal',
|
||||
font: new Font('normal'),
|
||||
titleFont: new Font('normal', 20, 'px', 700),
|
||||
winskin: 'winskin2.png',
|
||||
interval: 100,
|
||||
lineHeight: 4,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { GameUI } from '@/core/system';
|
||||
import { computed, defineComponent, ref, watch } from 'vue';
|
||||
import { SetupComponentOptions, TextContent } from '../components';
|
||||
import { DefaultProps, ElementLocator, Sprite } from '@/core/render';
|
||||
import { DefaultProps, ElementLocator, Sprite, Font } from '@/core/render';
|
||||
import { transitionedColor } from '../use';
|
||||
import { linear } from 'mutate-animate';
|
||||
import { Scroll } from '../components/scroll';
|
||||
@ -62,9 +62,9 @@ export const LeftStatusBar = defineComponent<StatusBarProps<ILeftHeroStatus>>(
|
||||
return num.toString().padStart(2, '0');
|
||||
};
|
||||
|
||||
const font1 = '18px normal';
|
||||
const font2 = 'bold 18px normal';
|
||||
const font3 = 'bold 14px normal';
|
||||
const font1 = new Font('normal', 18);
|
||||
const font2 = new Font('normal', 18, 'px', 700);
|
||||
const font3 = new Font('normal', 14, 'px', 700);
|
||||
|
||||
const iconLoc = (n: number): ElementLocator => {
|
||||
return [16, 76 + 44 * n, 32, 32];
|
||||
@ -201,8 +201,8 @@ export interface IRightHeroStatus {
|
||||
|
||||
export const RightStatusBar = defineComponent<StatusBarProps<IRightHeroStatus>>(
|
||||
p => {
|
||||
const font1 = '18px normal';
|
||||
const font2 = '16px normal';
|
||||
const font1 = new Font('normal', 18);
|
||||
const font2 = new Font('normal', 16);
|
||||
|
||||
const minimap = ref<Sprite>();
|
||||
const inNumpad = ref(false);
|
||||
@ -340,8 +340,7 @@ export const RightStatusBar = defineComponent<StatusBarProps<IRightHeroStatus>>(
|
||||
<TextContent
|
||||
loc={[10, 42, 160, 60]}
|
||||
text={skillDesc.value}
|
||||
fontFamily="normal"
|
||||
fontSize={14}
|
||||
font={new Font('normal', 14)}
|
||||
width={160}
|
||||
lineHeight={4}
|
||||
></TextContent>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { DefaultProps, ElementLocator } from '@/core/render';
|
||||
import { DefaultProps, ElementLocator, Font } from '@/core/render';
|
||||
import { computed, defineComponent, ref } from 'vue';
|
||||
import { SetupComponentOptions } from '../components';
|
||||
import {
|
||||
@ -82,7 +82,7 @@ export const PlayingToolbar = defineComponent<
|
||||
const loadIcon = core.statusBar.icons.load;
|
||||
const setIcon = core.statusBar.icons.settings;
|
||||
|
||||
const iconFont = '12px Verdana';
|
||||
const iconFont = new Font('Verdana', 12);
|
||||
|
||||
const book = () => core.openBook(true);
|
||||
const tool = () => core.openEquipbox(true);
|
||||
@ -160,8 +160,8 @@ export const ReplayingToolbar = defineComponent<ReplayingProps>(props => {
|
||||
|
||||
const bookIcon = core.statusBar.icons.book;
|
||||
const saveIcon = core.statusBar.icons.save;
|
||||
const font1 = '16px normal';
|
||||
const font2 = '12px Verdana';
|
||||
const font1 = new Font('normal', 16);
|
||||
const font2 = new Font('Verdana', 12);
|
||||
|
||||
const speedText = computed(() => `${status.speed}速`);
|
||||
const progress = computed(() => status.played / status.total);
|
||||
|
Loading…
Reference in New Issue
Block a user