mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-10-08 03:11:46 +08:00
fix: 文本框的配置问题
This commit is contained in:
parent
71c88369e1
commit
5bdd41159b
@ -174,6 +174,8 @@ export const TextContent = defineComponent<
|
||||
const renderContent = (canvas: MotaOffscreenCanvas2D) => {
|
||||
const ctx = canvas.ctx;
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.lineWidth = props.strokeWidth ?? 2;
|
||||
ctx.lineJoin = 'round';
|
||||
for (const data of renderable) {
|
||||
if (data.cut) break;
|
||||
switch (data.type) {
|
||||
@ -182,14 +184,15 @@ export const TextContent = defineComponent<
|
||||
ctx.fillStyle = data.fillStyle;
|
||||
ctx.strokeStyle = data.strokeStyle;
|
||||
ctx.font = data.font;
|
||||
|
||||
const text = data.text.slice(0, data.pointer);
|
||||
|
||||
if (props.fill ?? true) {
|
||||
ctx.fillText(text, data.x, data.y);
|
||||
}
|
||||
if (props.stroke) {
|
||||
ctx.strokeText(text, data.x, data.y);
|
||||
}
|
||||
if (props.fill ?? true) {
|
||||
ctx.fillText(text, data.x, data.y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TextContentType.Icon: {
|
||||
@ -250,7 +253,7 @@ export interface TextboxProps extends TextContentProps, DefaultProps {
|
||||
/** 标题文字与边框间的距离,默认为4 */
|
||||
titlePadding?: number;
|
||||
/** 图标 */
|
||||
icon?: AllIds;
|
||||
icon?: AllIdsWithNone;
|
||||
/** 最大宽度 */
|
||||
width: number;
|
||||
}
|
||||
@ -408,8 +411,8 @@ export const Textbox = defineComponent<
|
||||
titleElement.value?.requestBeforeFrame(() => {
|
||||
if (titleElement.value) {
|
||||
const { width, height } = titleElement.value;
|
||||
tw.value = width + data.padding! * 2;
|
||||
th.value = height + data.padding! * 2;
|
||||
tw.value = width + data.titlePadding! * 2;
|
||||
th.value = height + data.titlePadding! * 2;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -481,7 +484,7 @@ export const Textbox = defineComponent<
|
||||
id={props.id}
|
||||
hidden={hidden.value}
|
||||
alpha={data.alpha}
|
||||
loc={props.loc}
|
||||
loc={data.loc}
|
||||
>
|
||||
{data.title && (
|
||||
<container zIndex={10} loc={[0, 0, tw.value, th.value]}>
|
||||
@ -502,6 +505,7 @@ export const Textbox = defineComponent<
|
||||
fillStyle={data.titleFill}
|
||||
strokeStyle={data.titleStroke}
|
||||
font={data.titleFont}
|
||||
strokeWidth={2}
|
||||
></text>
|
||||
</container>
|
||||
)}
|
||||
@ -520,7 +524,7 @@ export const Textbox = defineComponent<
|
||||
></g-rect>
|
||||
)}
|
||||
{hasIcon.value && (
|
||||
<icon icon={data.icon!} loc={iconLoc.value} animate />
|
||||
<icon icon={data.icon as AllIds} loc={iconLoc.value} animate />
|
||||
)}
|
||||
{hasIcon.value && (
|
||||
<g-rect
|
||||
|
@ -336,6 +336,12 @@ export class TextContentTyper extends EventEmitter<TextContentTyperEvent> {
|
||||
this.config[key] = value;
|
||||
}
|
||||
}
|
||||
if (config.font) {
|
||||
this.config.fontFamily = config.font.family;
|
||||
this.config.fontSize = config.font.size;
|
||||
this.config.fontItalic = config.font.italic;
|
||||
this.config.fontWeight = config.font.weight;
|
||||
}
|
||||
this.parser.setStatus({
|
||||
fillStyle: this.config.fillStyle,
|
||||
fontFamily: this.config.fontFamily,
|
||||
@ -528,7 +534,8 @@ export class TextContentTyper extends EventEmitter<TextContentTyperEvent> {
|
||||
return;
|
||||
}
|
||||
this.emit('typeStart');
|
||||
this.lastTypeTime = Date.now();
|
||||
// 减去间隔是为了第一个字可以立刻打出来,不然看起来有延迟
|
||||
this.lastTypeTime = Date.now() - this.config.interval - 1;
|
||||
this.typing = true;
|
||||
}
|
||||
|
||||
@ -628,11 +635,11 @@ export class TextContentParser {
|
||||
* @param st 要设置为的状态,不填的表示不变
|
||||
*/
|
||||
setStatus(st: Partial<ParserStatus>) {
|
||||
if (!isNil(st.fillStyle)) this.status.fillStyle = st.fillStyle;
|
||||
if (!isNil(st.fontSize)) this.status.fontSize = st.fontSize;
|
||||
if (!isNil(st.fontFamily)) this.status.fontFamily = st.fontFamily;
|
||||
if (!isNil(st.fontItalic)) this.status.fontItalic = st.fontItalic;
|
||||
if (!isNil(st.fontWeight)) this.status.fontWeight = st.fontWeight;
|
||||
if (!isNil(st.fillStyle)) this.initStatus.fillStyle = st.fillStyle;
|
||||
if (!isNil(st.fontSize)) this.initStatus.fontSize = st.fontSize;
|
||||
if (!isNil(st.fontFamily)) this.initStatus.fontFamily = st.fontFamily;
|
||||
if (!isNil(st.fontItalic)) this.initStatus.fontItalic = st.fontItalic;
|
||||
if (!isNil(st.fontWeight)) this.initStatus.fontWeight = st.fontWeight;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -856,6 +863,7 @@ export class TextContentParser {
|
||||
this.font = this.buildFont();
|
||||
this.resolved = '';
|
||||
this.wordBreak = [0];
|
||||
this.wordBreakRule = this.config.wordBreak;
|
||||
this.nodePointer = 0;
|
||||
this.blockPointer = 0;
|
||||
this.nowNode = 0;
|
||||
@ -975,7 +983,6 @@ export class TextContentParser {
|
||||
}
|
||||
|
||||
this.addTextNode(text.length, false);
|
||||
|
||||
return this.splitLines(width);
|
||||
}
|
||||
|
||||
@ -1198,7 +1205,11 @@ export class TextContentParser {
|
||||
this.newLine();
|
||||
const nextStart = this.wordBreak[index];
|
||||
const nextEnd = this.wordBreak[end];
|
||||
this.bsStart = index;
|
||||
if (index === this.bsStart) {
|
||||
this.bsStart = this.bsStart + 1;
|
||||
} else {
|
||||
this.bsStart = index;
|
||||
}
|
||||
this.bsEnd = end;
|
||||
const metrics = this.measure(node, nextStart, nextEnd);
|
||||
if (metrics.width < width) {
|
||||
@ -1338,11 +1349,9 @@ export class TextContentParser {
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const node = nodes[i];
|
||||
if (node.type === TextContentType.Text) {
|
||||
this.wordBreak = [node.text.length];
|
||||
this.wordBreak = [0, node.text.length];
|
||||
}
|
||||
const pointer =
|
||||
node.type === TextContentType.Text ? node.text.length : 1;
|
||||
const block = this.generateBlock(node, pointer);
|
||||
const block = this.generateBlock(node, 1);
|
||||
this.pushBlock(block, 1);
|
||||
}
|
||||
this.newLine();
|
||||
|
@ -66,7 +66,7 @@ export class Icon extends RenderItem<EIconEvent> implements IAnimateFrame {
|
||||
* 设置图标
|
||||
* @param id 图标id
|
||||
*/
|
||||
setIcon(id: AllIds | AllNumbers) {
|
||||
setIcon(id: AllIdsWithNone | AllNumbers) {
|
||||
if (id === 0 || id === 'none') {
|
||||
this.renderable = void 0;
|
||||
return;
|
||||
|
@ -83,7 +83,7 @@ const MainScene = defineComponent(() => {
|
||||
font: new Font('normal'),
|
||||
titleFont: new Font('normal', 20, 'px', 700),
|
||||
winskin: 'winskin2.png',
|
||||
interval: 100,
|
||||
interval: 30,
|
||||
lineHeight: 4,
|
||||
width: MAP_WIDTH
|
||||
};
|
||||
|
@ -52,6 +52,7 @@ export class Text extends RenderItem<ETextEvent> {
|
||||
ctx.strokeStyle = this.strokeStyle ?? 'transparent';
|
||||
ctx.font = this.font.string();
|
||||
ctx.lineWidth = this.strokeWidth;
|
||||
ctx.lineJoin = 'round';
|
||||
|
||||
if (this.strokeStyle) {
|
||||
ctx.strokeText(this.text, stroke, this.descent + stroke + SAFE_PAD);
|
||||
|
@ -1044,7 +1044,7 @@ setText_s
|
||||
tooltip : setText:设置文本的属性,颜色为RGB三元组或RGBA四元组,打字间隔为剧情文字添加的时间间隔,为整数或不填,字符间距为字符之间的距离,为整数或不填。
|
||||
helpUrl : /_docs/#/instruction
|
||||
previewBlock : true
|
||||
default : ["main-textbox","","","","","","","",false,false,"","","",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',"",true,false,"",'rgba(255,255,255,1)',"","",true,false,"",'null','null',"","",""]
|
||||
default : ["main-textbox","","","","","","","",false,false,"","","",'rgba(255,255,255,1)',"",'rgba(0,0,0,1)',"",true,false,"",'rgba(0,0,0,0.9)',"","",true,false,"",'null','null',"","",""]
|
||||
Bool_0 = Bool_0 ? (', "fontItalic": '+Bool_0) : '';
|
||||
Bool_1 = Bool_1 ? (', "keepLast": '+Bool_1) : '';
|
||||
Bool_2 = !Bool_2 ? (', "fill": '+Bool_2) : '';
|
||||
@ -1057,7 +1057,7 @@ IntString_2 = IntString_2 ? (', "width": '+IntString_2) : '';
|
||||
IntString_3 = IntString_3 ? (', "height": '+IntString_3) : '';
|
||||
IntString_4 = IntString_4 ? (', "fontSize": '+IntString_4) : '';
|
||||
IntString_5 = IntString_5? (', "fontWeight": ' + IntString_5) : '';
|
||||
IntString_6 = IntString_6 ? (', " interval": '+IntString_6) : '';
|
||||
IntString_6 = IntString_6 ? (', "interval": '+IntString_6) : '';
|
||||
IntString_7 = IntString_7 ? (', "lineHeight": ' + IntString_7) : '';
|
||||
IntString_8 = IntString_8? (', "strokeWidth": ' + IntString_8) : '';
|
||||
IntString_9 = IntString_9? (', "padding": ' + IntString_9) : '';
|
||||
|
@ -1579,7 +1579,15 @@ events.prototype._action_text = function (data) {
|
||||
loc[3] ??= 200;
|
||||
const { x = loc[0], y = loc[1], width = loc[2], height = loc[3] } = data;
|
||||
store.show();
|
||||
store.modify({ title, icon, loc: [x, y, width, height], width });
|
||||
store.modify({
|
||||
title,
|
||||
icon,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
loc: [x, y, width, height]
|
||||
});
|
||||
store.setText(text);
|
||||
core.events.nowTextbox = textbox;
|
||||
};
|
||||
@ -1600,7 +1608,15 @@ events.prototype._action_autoText = function (data) {
|
||||
loc[3] ??= 200;
|
||||
const { x = loc[0], y = loc[1], width = loc[2], height = loc[3] } = data;
|
||||
store.show();
|
||||
store.modify({ title, icon, loc: [x, y, width, height], width });
|
||||
store.modify({
|
||||
title,
|
||||
icon,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
loc: [x, y, width, height]
|
||||
});
|
||||
store.setText(text);
|
||||
|
||||
setTimeout(() => {
|
||||
@ -1623,10 +1639,11 @@ events.prototype._action__label = function (data, x, y, prefix) {
|
||||
};
|
||||
|
||||
events.prototype._action_setText = function (data) {
|
||||
const isNil = value => value !== null && value !== void 0;
|
||||
const isNil = value => value === null || value === void 0;
|
||||
const { textbox = 'main-textbox' } = data;
|
||||
const Store = Mota.require('@user/client-modules').TextboxStore;
|
||||
const Font = Mota.require('@motajs/render-vue').Font;
|
||||
const { TextAlign, WordBreak } = Mota.require('@user/client-modules');
|
||||
const Font = Mota.require('@motajs/render-style').Font;
|
||||
const store = Store.get(textbox);
|
||||
if (!store) {
|
||||
core.doAction();
|
||||
@ -1651,6 +1668,10 @@ events.prototype._action_setText = function (data) {
|
||||
});
|
||||
// config
|
||||
const config = {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
loc: newLoc,
|
||||
font: newFont,
|
||||
keepLast: data.keepLast,
|
||||
@ -1664,15 +1685,36 @@ events.prototype._action_setText = function (data) {
|
||||
backColor: data.backColor,
|
||||
winskin: data.winskin,
|
||||
padding: data.padding,
|
||||
titleFill: isNil(data.titleFill),
|
||||
titleStroke: !!data.titleStroke,
|
||||
titleFill: isNil(data.titleFill) ? 'gold' : 'transparent',
|
||||
titleStroke: data.titleStroke ? 'black' : 'transparent',
|
||||
titlePadding: data.titlePadding,
|
||||
textAlign: data.textAlign,
|
||||
wordBreak: data.wordBreak,
|
||||
ignoreLineStart: data.ignoreLineStart,
|
||||
ignoreLineEnd: data.ignoreLineEnd,
|
||||
breakChars: data.breakChars
|
||||
};
|
||||
switch (data.textAlign) {
|
||||
case 'left':
|
||||
config.textAlign = TextAlign.Left;
|
||||
break;
|
||||
case 'center':
|
||||
config.textAlign = TextAlign.Center;
|
||||
break;
|
||||
case 'right':
|
||||
config.textAlign = TextAlign.Right;
|
||||
break;
|
||||
}
|
||||
switch (data.wordBreak) {
|
||||
case 'none':
|
||||
config.wordBreak = WordBreak.None;
|
||||
break;
|
||||
case 'space':
|
||||
config.wordBreak = WordBreak.Space;
|
||||
break;
|
||||
case 'all':
|
||||
config.wordBreak = WordBreak.All;
|
||||
break;
|
||||
}
|
||||
|
||||
store.modify(config);
|
||||
|
||||
core.doAction();
|
||||
|
4
src/types/declaration/source.d.ts
vendored
4
src/types/declaration/source.d.ts
vendored
@ -25,7 +25,9 @@ type ItemCls = 'tools' | 'items' | 'equips' | 'constants';
|
||||
/**
|
||||
* 所有的道具id
|
||||
*/
|
||||
type AllIds = keyof IdToNumber | 'none';
|
||||
type AllIds = keyof IdToNumber;
|
||||
|
||||
type AllIdsWithNone = AllIds | 'none';
|
||||
|
||||
/**
|
||||
* 所有的道具数字
|
||||
|
Loading…
Reference in New Issue
Block a user