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