From f9ab9fb73d84d9a8a6034c4e172d8f087a1343fe Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Sat, 11 Oct 2025 16:31:17 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=BE=93=E5=85=A5=E6=A1=86=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/render/components/input.tsx | 99 ++++++++++++++----- .../client-modules/src/render/ui/settings.tsx | 2 +- .../client-modules/src/render/utils/saves.ts | 25 ++--- packages/render-core/src/render.ts | 9 -- packages/render-core/src/transform.ts | 1 + src/styles.less | 3 +- 6 files changed, 91 insertions(+), 48 deletions(-) diff --git a/packages-user/client-modules/src/render/components/input.tsx b/packages-user/client-modules/src/render/components/input.tsx index 9f219b4..1dc4844 100644 --- a/packages-user/client-modules/src/render/components/input.tsx +++ b/packages-user/client-modules/src/render/components/input.tsx @@ -10,10 +10,11 @@ import { Transform } from '@motajs/render-core'; import { Font } from '@motajs/render-style'; -import { transitionedColor } from '../use'; +import { transitionedColor, useKey } from '../use'; import { linear } from 'mutate-animate'; import { Background, Selection } from './misc'; import { GameUI, IUIMountable, SetupComponentOptions } from '@motajs/system-ui'; +import { KeyCode } from '@motajs/client-base'; export interface InputProps extends DefaultProps, Partial { /** 输入框的提示内容 */ @@ -49,7 +50,16 @@ export type InputEmits = { }; const inputProps = { - props: ['placeholder', 'value', 'multiline'], + props: [ + 'loc', + 'placeholder', + 'value', + 'multiline', + 'border', + 'circle', + 'borderWidth', + 'pad' + ], emits: ['change', 'input', 'update:value'] } satisfies SetupComponentOptions; @@ -92,6 +102,10 @@ export const Input = defineComponent( width.value - padding.value * 2, height.value - padding.value * 2 ]); + const rectLoc = computed(() => { + const b = props.borderWidth ?? 1; + return [b, b, width.value - b * 2, height.value - b * 2]; + }); const borderColor = transitionedColor( props.border ?? '#ddd', @@ -112,6 +126,9 @@ export const Input = defineComponent( } }); ele.addEventListener('blur', () => { + if (ele) { + updateInput(ele.value); + } ele?.remove(); }); }; @@ -143,42 +160,52 @@ export const Input = defineComponent( if (!ele) createInput(props.multiline ?? false); if (!ele) return; // 计算当前绝对位置 - const renderer = MotaRenderer.get('render-main'); - const canvas = renderer?.getCanvas(); - if (!canvas) return; const chain: RenderItem[] = []; let now: RenderItem | undefined = root.value; + let renderer: MotaRenderer | undefined; if (!now) return; while (now) { chain.unshift(now); + if (now?.isRoot) { + renderer = now as MotaRenderer; + } now = now.parent; } - // 应用内边距偏移 - const { clientLeft, clientTop } = canvas; - const trans = new Transform(); - trans.translate(clientLeft, clientTop); - trans.scale(core.domStyle.scale); + const canvas = renderer?.getCanvas(); + if (!canvas) return; + + const w = width.value; + const h = height.value; + + const border = props.borderWidth ?? 1; + const inputWidth = w - border * 2; + const inputHeight = h - border * 2; + + // 应用根画布偏移 + const box = canvas.getBoundingClientRect(); + let trans = new Transform(); + trans.translate(box.x, box.y); + trans.scale(renderer?.getScale() ?? 1); for (const item of chain) { const { anchorX, anchorY, width, height } = item; trans.translate(-anchorX * width, -anchorY * height); - trans.multiply(item.transform); + trans = trans.multiply(item.transform); } - trans.translate(padding.value, padding.value); + trans.translate(border, border); // 构建CSS transform的matrix字符串 const [a, b, , c, d, , e, f] = trans.mat; const str = `matrix(${a},${b},${c},${d},${e},${f})`; - const w = width.value * core.domStyle.scale; - const h = height.value * core.domStyle.scale; const font = props.font ?? Font.defaults(); ele.style.transform = str; - ele.style.width = `${w - padding.value * 2}px`; - ele.style.height = `${h - padding.value * 2}px`; + ele.style.width = `${inputWidth}px`; + ele.style.height = `${inputHeight}px`; ele.style.font = font.string(); ele.style.color = String(props.fillStyle ?? 'white'); + ele.style.zIndex = '100'; document.body.appendChild(ele); ele.focus(); }; @@ -191,6 +218,14 @@ export const Input = defineComponent( borderColor.set(props.border ?? '#ddd'); }; + const [key] = useKey(); + key.realize('confirm', (_, code) => { + if (code === KeyCode.Enter) { + // 特判回车键 + ele?.blur(); + } + }); + watch( () => props.value, newValue => { @@ -214,6 +249,7 @@ export const Input = defineComponent( return () => ( ( onLeave={leave} > ( loc={textLoc.value} width={width.value - padding.value * 2} text={showText.value} + fillStyle="white" alpha={value.value.length === 0 ? 0.6 : 1} - zIndex={0} + zIndex={10} /> ); @@ -353,12 +393,12 @@ export const InputBox = defineComponent< const noText = computed(() => props.noText ?? '取消'); const text = computed(() => props.text ?? '请输入内容:'); const padding = computed(() => props.pad ?? 8); - const inputHeight = computed(() => props.inputHeight ?? 16); + const inputHeight = computed(() => props.inputHeight ?? 24); const inputLoc = computed(() => [ padding.value, padding.value * 2 + contentHeight.value, props.width - padding.value * 2, - inputHeight.value - padding.value * 2 + inputHeight.value ]); const yesLoc = computed(() => { const y = height.value - padding.value; @@ -379,10 +419,17 @@ export const InputBox = defineComponent< return [x, y + 4, width + 8, height + 8, 0.5, 1]; } }); + const boxLoc = computed(() => { + const [x = 0, y = 0, , , ax = 0, ay = 0] = props.loc; + return [x, y, props.width, height.value, ax, ay]; + }); const updateHeight = (h: number) => { contentHeight.value = h; - height.value = h + inputHeight.value + padding.value * 4; + const [, yh] = yesSize.value; + const [, nh] = noSize.value; + const buttonHeight = Math.max(yh, nh); + height.value = h + inputHeight.value + padding.value * 4 + buttonHeight; }; const change = (value: string) => { @@ -411,11 +458,11 @@ export const InputBox = defineComponent< }; return () => ( - + @@ -426,12 +473,14 @@ export const InputBox = defineComponent< width={props.width - padding.value * 2} zIndex={5} onUpdateHeight={updateHeight} + autoHeight /> diff --git a/packages-user/client-modules/src/render/ui/settings.tsx b/packages-user/client-modules/src/render/ui/settings.tsx index a29273c..3fe3c2d 100644 --- a/packages-user/client-modules/src/render/ui/settings.tsx +++ b/packages-user/client-modules/src/render/ui/settings.tsx @@ -364,7 +364,7 @@ export const SyncSave = defineComponent(props => { [SyncSaveChoice.ToServer, '同步存档至服务器'], [SyncSaveChoice.FromServer, '从服务器加载存档'], [SyncSaveChoice.ToLocal, '存档至本地文件'], - [SyncSaveChoice.FromLocal, '存本地文件读档'], + [SyncSaveChoice.FromLocal, '从本地文件读档'], [SyncSaveChoice.ClearLocal, '清空本地存档'], [SyncSaveChoice.Back, '返回上一级'] ]; diff --git a/packages-user/client-modules/src/render/utils/saves.ts b/packages-user/client-modules/src/render/utils/saves.ts index 51f6a89..5524ad0 100644 --- a/packages-user/client-modules/src/render/utils/saves.ts +++ b/packages-user/client-modules/src/render/utils/saves.ts @@ -2,6 +2,7 @@ import { compressToBase64, decompressFromBase64 } from 'lz-string'; import { getConfirm, waitbox } from '../components'; import { IUIMountable } from '@motajs/system-ui'; import { SyncSaveFromServerResponse } from '@motajs/client-base'; +import { CENTER_LOC, POP_BOX_WIDTH } from '../shared'; export interface SaveData { name: string; @@ -128,15 +129,15 @@ export async function syncFromServer( return void getConfirm( controller, '不合法的存档编号+密码!请检查格式!', - [240, 240, void 0, void 0, 0.5, 0.5], - 240 + CENTER_LOC, + POP_BOX_WIDTH ); } const [id, password] = parseIdPassword(identifier); const result = await waitbox( controller, - [240, 240, void 0, void 0, 0.5, 0.5], - 240, + CENTER_LOC, + POP_BOX_WIDTH, syncLoad(id, password) ); if (typeof result === 'number') { @@ -150,16 +151,16 @@ export async function syncFromServer( return void getConfirm( controller, map[result], - [240, 240, void 0, void 0, 0.5, 0.5], - 240 + CENTER_LOC, + POP_BOX_WIDTH ); } if (result instanceof Array) { const confirm = await getConfirm( controller, '所有本地存档都将被覆盖,确认?', - [240, 240, void 0, void 0, 0.5, 0.5], - 240, + CENTER_LOC, + POP_BOX_WIDTH, { defaultYes: true } @@ -176,8 +177,8 @@ export async function syncFromServer( return void getConfirm( controller, '同步成功!\n你的本地所有存档均已被覆盖。', - [240, 240, void 0, void 0, 0.5, 0.5], - 240 + CENTER_LOC, + POP_BOX_WIDTH ); } } else { @@ -188,8 +189,8 @@ export async function syncFromServer( return void getConfirm( controller, `同步成功!\n单存档已覆盖至存档 ${idx}`, - [240, 240, void 0, void 0, 0.5, 0.5], - 240 + CENTER_LOC, + POP_BOX_WIDTH ); } } diff --git a/packages/render-core/src/render.ts b/packages/render-core/src/render.ts index 80fdf72..16668b7 100644 --- a/packages/render-core/src/render.ts +++ b/packages/render-core/src/render.ts @@ -133,7 +133,6 @@ export class MotaRenderer extends Container implements IRenderTreeRoot { // 画布监听 const canvas = this.target.canvas; canvas.addEventListener('mousedown', ev => { - ev.preventDefault(); const mouse = this.getMouseType(ev); this.lastMouse = mouse; this.captureEvent( @@ -142,13 +141,11 @@ export class MotaRenderer extends Container implements IRenderTreeRoot { ); }); canvas.addEventListener('mouseup', ev => { - ev.preventDefault(); const event = this.createMouseAction(ev, ActionType.Up); this.captureEvent(ActionType.Up, event); this.captureEvent(ActionType.Click, event); }); canvas.addEventListener('mousemove', ev => { - ev.preventDefault(); const event = this.createMouseAction( ev, ActionType.Move, @@ -171,7 +168,6 @@ export class MotaRenderer extends Container implements IRenderTreeRoot { ); }); canvas.addEventListener('mouseleave', ev => { - ev.preventDefault(); const id = this.getMouseIdentifier( ActionType.Leave, this.getMouseType(ev) @@ -183,13 +179,11 @@ export class MotaRenderer extends Container implements IRenderTreeRoot { this.beforeHovered.clear(); }); document.addEventListener('touchstart', ev => { - ev.preventDefault(); this.createTouchAction(ev, ActionType.Down).forEach(v => { this.captureEvent(ActionType.Down, v); }); }); document.addEventListener('touchend', ev => { - ev.preventDefault(); this.createTouchAction(ev, ActionType.Up).forEach(v => { this.captureEvent(ActionType.Up, v); this.captureEvent(ActionType.Click, v); @@ -199,7 +193,6 @@ export class MotaRenderer extends Container implements IRenderTreeRoot { }); }); document.addEventListener('touchcancel', ev => { - ev.preventDefault(); this.createTouchAction(ev, ActionType.Up).forEach(v => { this.captureEvent(ActionType.Up, v); }); @@ -208,7 +201,6 @@ export class MotaRenderer extends Container implements IRenderTreeRoot { }); }); document.addEventListener('touchmove', ev => { - ev.preventDefault(); this.createTouchAction(ev, ActionType.Move).forEach(v => { const list = this.touchInfo.values(); if (!list.some(vv => v.identifier === vv.identifier)) { @@ -228,7 +220,6 @@ export class MotaRenderer extends Container implements IRenderTreeRoot { }); }); canvas.addEventListener('wheel', ev => { - ev.preventDefault(); this.captureEvent( ActionType.Wheel, this.createWheelAction(ev, ActionType.Wheel) diff --git a/packages/render-core/src/transform.ts b/packages/render-core/src/transform.ts index af53975..97b0d02 100644 --- a/packages/render-core/src/transform.ts +++ b/packages/render-core/src/transform.ts @@ -192,6 +192,7 @@ export class Transform { if (this.modified) { const result = new Transform(); mat3.multiply(result.mat, this.mat, transform.mat); + result.modified = true; return result; } else { return transform.clone(); diff --git a/src/styles.less b/src/styles.less index ae3357c..d9bb99e 100644 --- a/src/styles.less +++ b/src/styles.less @@ -127,5 +127,6 @@ div.toolbar-editor-item { position: fixed; border: none; z-index: 1000; - background-color: transparent; + background-color: black; + transform-origin: 0 0; }