From 91e448fdcc6970a0f0c6ea8954e03622a52e3f7c Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Mon, 24 Feb 2025 11:37:05 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20enter=20=E5=92=8C=20leave=20?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6=20&=20=20patchProp=20=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/render/container.ts | 15 +- src/core/render/event.ts | 39 ++- src/core/render/item.ts | 59 ++-- src/core/render/preset/damage.ts | 39 ++- src/core/render/preset/graphics.ts | 291 ++++++++++--------- src/core/render/preset/layer.ts | 65 ++--- src/core/render/preset/misc.ts | 85 +++--- src/core/render/render.ts | 129 ++++++-- src/core/render/renderer/elements.tsx | 2 +- src/core/render/renderer/index.ts | 7 + src/core/render/renderer/props.ts | 22 +- src/core/render/sprite.ts | 17 +- src/module/render/components/misc.tsx | 4 +- src/module/render/components/page.tsx | 25 +- src/module/render/components/scroll.tsx | 3 +- src/module/render/components/textbox.tsx | 8 +- src/module/render/components/textboxTyper.ts | 2 - 17 files changed, 467 insertions(+), 345 deletions(-) diff --git a/src/core/render/container.ts b/src/core/render/container.ts index 44a02fd..8eedd80 100644 --- a/src/core/render/container.ts +++ b/src/core/render/container.ts @@ -1,4 +1,3 @@ -import { ElementNamespace, ComponentInternalInstance } from 'vue'; import { MotaOffscreenCanvas2D } from '../fx/canvas2d'; import { ActionType, EventProgress, ActionEventMap } from './event'; import { @@ -168,20 +167,18 @@ export class ContainerCustom extends Container { this.renderFn = render; } - patchProp( + protected handleProps( key: string, prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { + nextValue: any + ): boolean { switch (key) { case 'render': { - if (!this.assertType(nextValue, 'function', key)) return; + if (!this.assertType(nextValue, 'function', key)) return false; this.setRenderFn(nextValue); - return; + return true; } } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return super.handleProps(key, prevValue, nextValue); } } diff --git a/src/core/render/event.ts b/src/core/render/event.ts index 86cd660..1161599 100644 --- a/src/core/render/event.ts +++ b/src/core/render/event.ts @@ -49,21 +49,11 @@ export const enum EventProgress { Bubble } -export interface IActionEvent { +export interface IActionEventBase { /** 当前事件是监听的哪个元素 */ target: RenderItem; - /** 这次操作的标识符,在按下、移动、抬起阶段中保持不变 */ - identifier: number; /** 是触摸操作还是鼠标操作 */ touch: boolean; - /** 相对于触发元素左上角的横坐标 */ - offsetX: number; - /** 相对于触发元素左上角的纵坐标 */ - offsetY: number; - /** 相对于整个画布左上角的横坐标 */ - absoluteX: number; - /** 相对于整个画布左上角的纵坐标 */ - absoluteY: number; /** * 触发的按键种类,会出现在点击、按下、抬起三个事件中,而其他的如移动等该值只会是 {@link MouseType.None}, * 电脑端可以有左键、中键、右键等,手机只会触发左键,每一项的值参考 {@link MouseType} @@ -83,6 +73,19 @@ export interface IActionEvent { ctrlKey: boolean; /** 触发时是否按下了 Windows(Windows) / Command(Mac) 键 */ metaKey: boolean; +} + +export interface IActionEvent extends IActionEventBase { + /** 这次操作的标识符,在按下、移动、抬起阶段中保持不变 */ + identifier: number; + /** 相对于触发元素左上角的横坐标 */ + offsetX: number; + /** 相对于触发元素左上角的纵坐标 */ + offsetY: number; + /** 相对于整个画布左上角的横坐标 */ + absoluteX: number; + /** 相对于整个画布左上角的纵坐标 */ + absoluteY: number; /** * 调用后将停止事件的继续传播。 @@ -120,14 +123,10 @@ export interface ERenderItemActionEvent { upCapture: [ev: Readonly]; /** 当鼠标或手指在该元素上抬起的冒泡阶段触发 */ up: [ev: Readonly]; - /** 当鼠标或手指进入该元素的捕获阶段触发 */ - enterCapture: [ev: Readonly]; - /** 当鼠标或手指进入该元素的冒泡阶段触发 */ - enter: [ev: Readonly]; - /** 当鼠标或手指离开该元素的捕获阶段触发 */ - leaveCapture: [ev: Readonly]; - /** 当鼠标或手指离开该元素的冒泡阶段触发 */ - leave: [ev: Readonly]; + /** 当鼠标或手指进入该元素时触发 */ + enter: [ev: Readonly]; + /** 当鼠标或手指离开该元素时触发 */ + leave: [ev: Readonly]; /** 当鼠标滚轮时的捕获阶段触发 */ wheelCapture: [ev: Readonly]; /** 当鼠标滚轮时的冒泡阶段触发 */ @@ -144,7 +143,7 @@ export interface ActionEventMap { [ActionType.Wheel]: IWheelEvent; } -export const eventNameMap: Record = { +export const eventNameMap: Record = { [ActionType.Click]: 'click', [ActionType.Down]: 'down', [ActionType.Move]: 'move', diff --git a/src/core/render/item.ts b/src/core/render/item.ts index 434f617..78a4625 100644 --- a/src/core/render/item.ts +++ b/src/core/render/item.ts @@ -272,7 +272,9 @@ export abstract class RenderItem alpha: number = 1; /** 鼠标覆盖在此元素上时的光标样式 */ - cursor: string = 'auto'; + cursor: string = 'inherit'; + /** 该元素是否忽略交互事件 */ + noEvent: boolean = false; get x() { return this._transform.x; @@ -340,14 +342,12 @@ export abstract class RenderItem private cachedEvent: Map = new Map(); /** 下穿模式下当前下穿过来的变换矩阵 */ private fallTransform?: Transform; - /** 鼠标当前是否覆盖在当前元素上 */ - private hovered: boolean = false; /** 是否在元素内 */ private inElement: boolean = false; /** 鼠标标识符映射,键为按下的鼠标按键类型,值表示本次操作的唯一标识符,在按下、移动、抬起过程中保持一致 */ protected mouseId: Map = new Map(); /** 当前所有的触摸标识符 */ - protected touchId: Set = new Set(); + readonly touchId: Set = new Set(); //#endregion @@ -650,7 +650,7 @@ export abstract class RenderItem //#region 父子关系 - checkRoot() { + checkRoot(): RenderItem | null { if (this._root) return this._root; if (this.isRoot) return this; let ele: RenderItem = this; @@ -756,10 +756,12 @@ export abstract class RenderItem type: ActionType, progress: EventProgress ): keyof ERenderItemActionEvent { - if (progress === EventProgress.Capture) { + if (type === ActionType.Enter || type === ActionType.Leave) { + return eventNameMap[type]; + } else if (progress === EventProgress.Capture) { return `${eventNameMap[type]}Capture` as keyof ERenderItemActionEvent; } else { - return eventNameMap[type] as keyof ERenderItemActionEvent; + return eventNameMap[type]; } } @@ -829,6 +831,7 @@ export abstract class RenderItem progress: EventProgress, event: ActionEventMap[T] ): ActionEventMap[T] | null { + if (this.noEvent) return null; if (progress === EventProgress.Capture) { // 捕获阶段需要计算鼠标位置 const tran = this.transformFallThrough @@ -836,7 +839,6 @@ export abstract class RenderItem : this._transform; if (!tran) return null; const [nx, ny] = this.calActionPosition(event, tran); - const inElement = this.isActionInElement(nx, ny); // 在元素范围内,执行事件 const newEvent: ActionEventMap[T] = { @@ -877,17 +879,6 @@ export abstract class RenderItem if (inElement) { this._root?.hoverElement(this); } - if (this.hovered && !inElement) { - this.hovered = false; - this.emit('leaveCapture', event); - this.emit('leave', event); - return false; - } else if (!this.hovered && inElement) { - this.hovered = true; - this.emit('enterCapture', event); - this.emit('enter', event); - return true; - } break; } case ActionType.Down: { @@ -929,10 +920,15 @@ export abstract class RenderItem * @returns 是否继续传递事件 */ protected processBubble( - _type: T, + type: T, _event: ActionEventMap[T], inElement: boolean ): boolean { + switch (type) { + case ActionType.Enter: + case ActionType.Leave: + return false; + } return inElement; } @@ -1039,6 +1035,21 @@ export abstract class RenderItem return false; } + /** + * 自定义处理 props,自定义元素需要 override 此函数来处理 props + * @param key 传入的 props 的键名 + * @param prevValue 这个 props 之前的值 + * @param nextValue 这个 props 传入的值 + * @returns 是否处理成功 + */ + protected handleProps( + _key: string, + _prevValue: any, + _nextValue: any + ): boolean { + return false; + } + patchProp( key: string, prevValue: any, @@ -1047,6 +1058,7 @@ export abstract class RenderItem _parentComponent?: ComponentInternalInstance | null ): void { if (isNil(prevValue) && isNil(nextValue)) return; + if (this.handleProps(key, prevValue, nextValue)) return; switch (key) { case 'x': { if (!this.assertType(nextValue, 'number', key)) return; @@ -1093,11 +1105,16 @@ export abstract class RenderItem this.setHD(nextValue); return; } - case 'antiAliasing': { + case 'anti': { if (!this.assertType(nextValue, 'boolean', key)) return; this.setAntiAliasing(nextValue); return; } + case 'noanti': { + if (!this.assertType(nextValue, 'boolean', key)) return; + this.setAntiAliasing(!nextValue); + return; + } case 'hidden': { if (!this.assertType(nextValue, 'boolean', key)) return; if (nextValue) this.hide(); diff --git a/src/core/render/preset/damage.ts b/src/core/render/preset/damage.ts index 7d076f3..c0743ef 100644 --- a/src/core/render/preset/damage.ts +++ b/src/core/render/preset/damage.ts @@ -18,7 +18,6 @@ import { getDamageColor } from '@/plugin/utils'; import { ERenderItemEvent, RenderItem } from '../item'; import EventEmitter from 'eventemitter3'; import { Transform } from '../transform'; -import { ElementNamespace, ComponentInternalInstance } from 'vue'; import { transformCanvas } from '../utils'; const ensureFloorDamage = Mota.require('fn', 'ensureFloorDamage'); @@ -529,46 +528,44 @@ export class Damage extends RenderItem { // console.timeEnd('damage'); } - patchProp( + protected handleProps( key: string, - prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { + _prevValue: any, + nextValue: any + ): boolean { switch (key) { case 'mapWidth': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setMapSize(nextValue, this.mapHeight); - return; + return true; case 'mapHeight': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setMapSize(this.mapWidth, nextValue); - return; + return true; case 'cellSize': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setCellSize(nextValue); - return; + return true; case 'enemy': - if (!this.assertType(nextValue, 'object', key)) return; + if (!this.assertType(nextValue, 'object', key)) return false; this.updateCollection(nextValue); - return; + return true; case 'font': - if (!this.assertType(nextValue, 'string', key)) return; + if (!this.assertType(nextValue, 'string', key)) return false; this.font = nextValue; this.update(); - return; + return true; case 'strokeStyle': this.strokeStyle = nextValue; this.update(); - return; + return true; case 'strokeWidth': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.strokeWidth = nextValue; this.update(); - return; + return true; } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return false; } destroy(): void { diff --git a/src/core/render/preset/graphics.ts b/src/core/render/preset/graphics.ts index 3418ab2..27b25d2 100644 --- a/src/core/render/preset/graphics.ts +++ b/src/core/render/preset/graphics.ts @@ -1,7 +1,6 @@ import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d'; import { ERenderItemEvent, RenderItem } from '../item'; import { Transform } from '../transform'; -import { ElementNamespace, ComponentInternalInstance } from 'vue'; import { clamp, isNil } from 'lodash-es'; import { logger } from '@/core/common/logger'; @@ -167,15 +166,22 @@ export abstract class GraphicItemBase } const path = this.cachePath; if (!path) return false; + const fixX = x * devicePixelRatio; + const fixY = y * devicePixelRatio; + ctx.lineWidth = this.lineWidth; + ctx.lineCap = this.lineCap; + ctx.lineJoin = this.lineJoin; + ctx.setLineDash(this.lineDash); switch (this.mode) { case GraphicMode.Fill: - return ctx.isPointInPath(path, x, y, this.fillRule); + return ctx.isPointInPath(path, fixX, fixY, this.fillRule); case GraphicMode.Stroke: + return ctx.isPointInStroke(path, fixX, fixY); case GraphicMode.FillAndStroke: case GraphicMode.StrokeAndFill: return ( - ctx.isPointInPath(path, x, y, this.fillRule) || - ctx.isPointInStroke(path, x, y) + ctx.isPointInPath(path, fixX, fixY, this.fillRule) || + ctx.isPointInStroke(path, fixX, fixY) ); } } @@ -287,69 +293,66 @@ export abstract class GraphicItemBase ctx.miterLimit = this.miterLimit; } - patchProp( + protected handleProps( key: string, - prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { - if (isNil(prevValue) && isNil(nextValue)) return; + _prevValue: any, + nextValue: any + ): boolean { switch (key) { case 'fill': - if (!this.assertType(nextValue, 'boolean', key)) return; + if (!this.assertType(nextValue, 'boolean', key)) return false; this.checkMode(GraphicModeProp.Fill, nextValue); - break; + return true; case 'stroke': - if (!this.assertType(nextValue, 'boolean', key)) return; + if (!this.assertType(nextValue, 'boolean', key)) return false; this.checkMode(GraphicModeProp.Stroke, nextValue); - break; + return true; case 'strokeAndFill': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.checkMode(GraphicModeProp.StrokeAndFill, nextValue); - break; + return true; case 'fillRule': - if (!this.assertType(nextValue, 'string', key)) return; + if (!this.assertType(nextValue, 'string', key)) return false; this.setFillRule(nextValue); - break; + return true; case 'fillStyle': this.setFillStyle(nextValue); - break; + return true; case 'strokeStyle': this.setStrokeStyle(nextValue); - break; + return true; case 'lineWidth': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.lineWidth = nextValue; this.update(); - break; + return true; case 'lineDash': - if (!this.assertType(nextValue, Array, key)) return; + if (!this.assertType(nextValue, Array, key)) return false; this.lineDash = nextValue as number[]; this.update(); - break; + return true; case 'lineDashOffset': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.lineDashOffset = nextValue; this.update(); - break; + return true; case 'lineJoin': - if (!this.assertType(nextValue, 'string', key)) return; + if (!this.assertType(nextValue, 'string', key)) return false; this.lineJoin = nextValue; this.update(); - break; + return true; case 'lineCap': - if (!this.assertType(nextValue, 'string', key)) return; + if (!this.assertType(nextValue, 'string', key)) return false; this.lineCap = nextValue; this.update(); - break; + return true; case 'miterLimit': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.miterLimit = nextValue; this.update(); - break; + return true; } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return false; } } @@ -407,29 +410,27 @@ export class Circle extends GraphicItemBase { this.update(); } - patchProp( + protected handleProps( key: string, prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { + nextValue: any + ): boolean { switch (key) { case 'radius': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setRadius(nextValue); - return; + return true; case 'start': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setAngle(nextValue, this.end); - return; + return true; case 'end': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setAngle(this.start, nextValue); - return; + return true; case 'circle': { const value = nextValue as CircleParams; - if (!this.assertType(value, Array, key)) return; + if (!this.assertType(value, Array, key)) return false; const [cx, cy, radius, start, end] = value; if (!isNil(cx) && !isNil(cy)) { this.pos(cx, cy); @@ -440,10 +441,10 @@ export class Circle extends GraphicItemBase { if (!isNil(start) && !isNil(end)) { this.setAngle(start, end); } - return; + return true; } } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return super.handleProps(key, prevValue, nextValue); } } @@ -494,33 +495,31 @@ export class Ellipse extends GraphicItemBase { this.update(); } - patchProp( + protected handleProps( key: string, prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { + nextValue: any + ): boolean { switch (key) { case 'radiusX': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setRadius(nextValue, this.radiusY); - return; + return true; case 'radiusY': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setRadius(this.radiusY, nextValue); - return; + return true; case 'start': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setAngle(nextValue, this.end); - return; + return true; case 'end': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setAngle(this.start, nextValue); - return; + return true; case 'ellipse': { const value = nextValue as EllipseParams; - if (!this.assertType(value, Array, key)) return; + if (!this.assertType(value, Array, key)) return false; const [cx, cy, radiusX, radiusY, start, end] = value; if (!isNil(cx) && !isNil(cy)) { this.pos(cx, cy); @@ -531,10 +530,10 @@ export class Ellipse extends GraphicItemBase { if (!isNil(start) && !isNil(end)) { this.setAngle(start, end); } - return; + return true; } } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return super.handleProps(key, prevValue, nextValue); } } @@ -584,37 +583,37 @@ export class Line extends GraphicItemBase { this.pathDirty = true; } - patchProp( + protected handleProps( key: string, prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { + nextValue: any + ): boolean { switch (key) { case 'x1': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setPoint1(nextValue, this.y1); - return; + return true; case 'y1': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setPoint1(this.x1, nextValue); - return; + return true; case 'x2': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setPoint2(nextValue, this.y2); - return; + return true; case 'y2': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setPoint2(this.x2, nextValue); - return; + return true; case 'line': - if (!this.assertType(nextValue as number[], Array, key)) return; + if (!this.assertType(nextValue as number[], Array, key)) { + return false; + } this.setPoint1(nextValue[0], nextValue[1]); this.setPoint2(nextValue[2], nextValue[3]); - return; + return true; } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return super.handleProps(key, prevValue, nextValue); } } @@ -685,6 +684,10 @@ export class BezierCurve extends GraphicItemBase { this.update(); } + protected isActionInElement(x: number, y: number): boolean { + return x >= 0 && x < this.width && y >= 0 && y < this.height; + } + private fitRect() { const left = Math.min(this.sx, this.cp1x, this.cp2x, this.ex); const top = Math.min(this.sy, this.cp1y, this.cp2y, this.ey); @@ -695,55 +698,55 @@ export class BezierCurve extends GraphicItemBase { this.pathDirty = true; } - patchProp( + protected handleProps( key: string, prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { + nextValue: any + ): boolean { switch (key) { case 'sx': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setStart(nextValue, this.sy); - return; + return true; case 'sy': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setStart(this.sx, nextValue); - return; + return true; case 'cp1x': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setControl1(nextValue, this.cp1y); - return; + return true; case 'cp1y': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setControl1(this.cp1x, nextValue); - return; + return true; case 'cp2x': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setControl2(nextValue, this.cp2y); - return; + return true; case 'cp2y': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setControl2(this.cp2x, nextValue); - return; + return true; case 'ex': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setEnd(nextValue, this.ey); - return; + return true; case 'ey': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setEnd(this.ex, nextValue); - return; + return true; case 'curve': - if (!this.assertType(nextValue as number[], Array, key)) return; + if (!this.assertType(nextValue as number[], Array, key)) { + return false; + } this.setStart(nextValue[0], nextValue[1]); this.setControl1(nextValue[2], nextValue[3]); this.setControl2(nextValue[4], nextValue[5]); this.setEnd(nextValue[6], nextValue[7]); - return; + return true; } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return super.handleProps(key, prevValue, nextValue); } } @@ -822,46 +825,50 @@ export class QuadraticCurve extends GraphicItemBase { this.pathDirty = true; } - patchProp( + protected isActionInElement(x: number, y: number): boolean { + return x >= 0 && x < this.width && y >= 0 && y < this.height; + } + + protected handleProps( key: string, prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { + nextValue: any + ): boolean { switch (key) { case 'sx': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setStart(nextValue, this.sy); - return; + return true; case 'sy': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setStart(this.sx, nextValue); - return; + return true; case 'cpx': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setControl(nextValue, this.cpy); - return; + return true; case 'cpy': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setControl(this.cpx, nextValue); - return; + return true; case 'ex': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setEnd(nextValue, this.ey); - return; + return true; case 'ey': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setEnd(this.ex, nextValue); - return; + return true; case 'curve': - if (!this.assertType(nextValue as number[], Array, key)) return; + if (!this.assertType(nextValue as number[], Array, key)) { + return false; + } this.setStart(nextValue[0], nextValue[1]); this.setControl(nextValue[2], nextValue[3]); this.setEnd(nextValue[4], nextValue[5]); - return; + return true; } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return super.handleProps(key, prevValue, nextValue); } } @@ -886,22 +893,24 @@ export class Path extends GraphicItemBase { this.update(); } - patchProp( + protected isActionInElement(x: number, y: number): boolean { + return x >= 0 && x < this.width && y >= 0 && y < this.height; + } + + protected handleProps( key: string, prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { + nextValue: any + ): boolean { switch (key) { case 'path': - if (!this.assertType(nextValue, Path2D, key)) return; + if (!this.assertType(nextValue, Path2D, key)) return false; this.path = nextValue; this.pathDirty = true; this.update(); - return; + return true; } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return super.handleProps(key, prevValue, nextValue); } } @@ -1041,27 +1050,25 @@ export class RectR extends GraphicItemBase { } } - patchProp( + protected handleProps( key: string, prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { + nextValue: any + ): boolean { switch (key) { case 'circle': { const value = nextValue as RectRCircleParams; - if (!this.assertType(value, Array, key)) return; + if (!this.assertType(value, Array, key)) return false; this.setCircle(value); - return; + return true; } case 'ellipse': { const value = nextValue as RectREllipseParams; - if (!this.assertType(value, Array, key)) return; + if (!this.assertType(value, Array, key)) return false; this.setEllipse(value); - return; + return true; } } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return super.handleProps(key, prevValue, nextValue); } } diff --git a/src/core/render/preset/layer.ts b/src/core/render/preset/layer.ts index a7e0914..6ea6f15 100644 --- a/src/core/render/preset/layer.ts +++ b/src/core/render/preset/layer.ts @@ -9,7 +9,6 @@ import { BlockCacher, CanvasCacheItem, ICanvasCacheItem } from './block'; import { Transform } from '../transform'; import { LayerFloorBinder, LayerGroupFloorBinder } from './floor'; import { RenderAdapter } from '../adapter'; -import { ElementNamespace, ComponentInternalInstance } from 'vue'; import { IAnimateFrame, renderEmits } from '../frame'; export interface ILayerGroupRenderExtends { @@ -332,36 +331,34 @@ export class LayerGroup } } - patchProp( + protected handleProps( key: string, - prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { + _prevValue: any, + nextValue: any + ): boolean { switch (key) { case 'cellSize': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setCellSize(nextValue); - return; + return true; case 'blockSize': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setBlockSize(nextValue); - return; + return true; case 'floorId': { - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; const binder = this.getExtends('floor-binder'); if (binder instanceof LayerGroupFloorBinder) { binder.bindFloor(nextValue); } - return; + return true; } case 'camera': - if (!this.assertType(nextValue, Transform, key)) return; + if (!this.assertType(nextValue, Transform, key)) return false; this.camera = nextValue; - return; + return true; } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return false; } destroy(): void { @@ -1438,16 +1435,14 @@ export class Layer extends Container { }); } - patchProp( + protected handleProps( key: string, - prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { + _prevValue: any, + nextValue: any + ): boolean { switch (key) { case 'layer': { - if (!this.assertType(nextValue, 'string', key)) return; + if (!this.assertType(nextValue, 'string', key)) return false; const parent = this.parent; if (parent instanceof LayerGroup) { parent.removeLayer(this); @@ -1457,30 +1452,30 @@ export class Layer extends Container { this.layer = nextValue; } this.update(); - return; + return true; } case 'cellSize': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setCellSize(nextValue); - return; + return true; case 'mapWidth': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setMapSize(nextValue, this.mapHeight); - return; + return true; case 'mapHeight': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setMapSize(this.mapWidth, nextValue); - return; + return true; case 'background': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setBackground(nextValue); - return; + return true; case 'floorImage': - if (!this.assertType(nextValue, Array, key)) return; + if (!this.assertType(nextValue, Array, key)) return false; this.setFloorImage(nextValue as FloorAnimate[]); - return; + return true; } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return false; } private addToGroup(group: LayerGroup) { diff --git a/src/core/render/preset/misc.ts b/src/core/render/preset/misc.ts index 9478f64..43973e8 100644 --- a/src/core/render/preset/misc.ts +++ b/src/core/render/preset/misc.ts @@ -1,7 +1,6 @@ import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d'; import { ERenderItemEvent, RenderItem, RenderItemPosition } from '../item'; import { Transform } from '../transform'; -import { ElementNamespace, ComponentInternalInstance } from 'vue'; import { AutotileRenderable, RenderableData } from '../cache'; import { texture } from '../cache'; import { isNil } from 'lodash-es'; @@ -114,33 +113,31 @@ export class Text extends RenderItem { this.size(width, actualBoundingBoxAscent + actualBoundingBoxDescent); } - patchProp( + protected handleProps( key: string, - prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { + _prevValue: any, + nextValue: any + ): boolean { switch (key) { case 'text': - if (!this.assertType(nextValue, 'string', key)) return; + if (!this.assertType(nextValue, 'string', key)) return false; this.setText(nextValue); - return; + return true; case 'fillStyle': this.setStyle(nextValue, this.strokeStyle); - return; + return true; case 'strokeStyle': this.setStyle(this.fillStyle, nextValue); - return; + return true; case 'font': - if (!this.assertType(nextValue, 'string', key)) return; + if (!this.assertType(nextValue, 'string', key)) return false; this.setFont(nextValue); break; case 'strokeWidth': this.setStrokeWidth(nextValue); - return; + return true; } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return false; } } @@ -181,19 +178,17 @@ export class Image extends RenderItem { this.update(); } - patchProp( + protected handleProps( key: string, - prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { + _prevValue: any, + nextValue: any + ): boolean { switch (key) { case 'image': this.setImage(nextValue); - return; + return true; } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return false; } } @@ -213,6 +208,10 @@ export class Comment extends RenderItem { _canvas: MotaOffscreenCanvas2D, _transform: Transform ): void {} + + protected handleProps(): boolean { + return false; + } } export interface EIconEvent extends ERenderItemEvent {} @@ -313,31 +312,29 @@ export class Icon extends RenderItem implements IAnimateFrame { super.destroy(); } - patchProp( + protected handleProps( key: string, - prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { + _prevValue: any, + nextValue: any + ): boolean { switch (key) { case 'icon': this.setIcon(nextValue); - return; + return true; case 'animate': - if (!this.assertType(nextValue, 'boolean', key)) return; + if (!this.assertType(nextValue, 'boolean', key)) return false; this.animate = nextValue; if (nextValue) renderEmits.addFramer(this); else renderEmits.removeFramer(this); this.update(); - return; + return true; case 'frame': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.frame = nextValue; this.update(); - return; + return true; } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return false; } } @@ -544,23 +541,21 @@ export class Winskin extends RenderItem { this.update(); } - patchProp( + protected handleProps( key: string, - prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { + _prevValue: any, + nextValue: any + ): boolean { switch (key) { case 'image': - if (!this.assertType(nextValue, 'string', key)) return; + if (!this.assertType(nextValue, 'string', key)) return false; this.setImageByName(nextValue); - return; + return true; case 'borderSize': - if (!this.assertType(nextValue, 'number', key)) return; + if (!this.assertType(nextValue, 'number', key)) return false; this.setBorderSize(nextValue); - return; + return true; } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return false; } } diff --git a/src/core/render/render.ts b/src/core/render/render.ts index f1259b8..f6fed43 100644 --- a/src/core/render/render.ts +++ b/src/core/render/render.ts @@ -2,9 +2,9 @@ import { logger } from '../common/logger'; import { MotaOffscreenCanvas2D } from '../fx/canvas2d'; import { Container } from './container'; import { - ActionEventMap, ActionType, IActionEvent, + IActionEventBase, IWheelEvent, MouseType, WheelType @@ -49,6 +49,10 @@ export class MotaRenderer extends Container implements IRenderTreeRoot { private abort?: AbortController; /** 根据捕获行为判断光标样式 */ private targetCursor: string = 'auto'; + /** 当前鼠标覆盖的元素 */ + private hoveredElement: Set = new Set(); + /** 本次交互前鼠标覆盖的元素 */ + private beforeHovered: Set = new Set(); target!: MotaOffscreenCanvas2D; @@ -112,17 +116,26 @@ export class MotaRenderer extends Container implements IRenderTreeRoot { this.lastMouse ); this.targetCursor = 'auto'; + const temp = this.beforeHovered; + temp.clear(); + this.beforeHovered = this.hoveredElement; + this.hoveredElement = temp; this.captureEvent(ActionType.Move, event); - }); - canvas.addEventListener('mouseenter', ev => { - const event = this.createMouseAction(ev, ActionType.Enter); - this.emit('enterCapture', event); - this.emit('enter', event); + if (this.targetCursor !== this.target.canvas.style.cursor) { + this.target.canvas.style.cursor = this.targetCursor; + } + this.checkMouseEnterLeave( + ev, + this.beforeHovered, + this.hoveredElement + ); }); canvas.addEventListener('mouseleave', ev => { - const event = this.createMouseAction(ev, ActionType.Leave); - this.emit('leaveCapture', event); - this.emit('leave', event); + this.hoveredElement.forEach(v => { + v.emit('leave', this.createMouseActionBase(ev, v)); + }); + this.hoveredElement.clear(); + this.beforeHovered.clear(); }); document.addEventListener('touchstart', ev => { this.createTouchAction(ev, ActionType.Down).forEach(v => { @@ -133,27 +146,29 @@ export class MotaRenderer extends Container implements IRenderTreeRoot { this.createTouchAction(ev, ActionType.Up).forEach(v => { this.captureEvent(ActionType.Up, v); this.captureEvent(ActionType.Click, v); + this.touchInfo.delete(v.identifier); }); }); document.addEventListener('touchcancel', ev => { this.createTouchAction(ev, ActionType.Up).forEach(v => { this.captureEvent(ActionType.Up, v); + this.touchInfo.delete(v.identifier); }); }); document.addEventListener('touchmove', ev => { this.createTouchAction(ev, ActionType.Move).forEach(v => { const touch = this.touchInfo.get(v.identifier); if (!touch) return; - const inElement = this.isTouchInCanvas(v.offsetX, v.offsetY); - if (touch.hovered && !inElement) { - this.emit('leaveCapture', v); - this.emit('leave', v); - } - if (!touch.hovered && inElement) { - this.emit('enterCapture', v); - this.emit('enter', v); - } + const temp = this.beforeHovered; + temp.clear(); + this.beforeHovered = this.hoveredElement; + this.hoveredElement = temp; this.captureEvent(ActionType.Move, v); + this.checkTouchEnterLeave( + ev, + this.beforeHovered, + this.hoveredElement + ); }); }); canvas.addEventListener('wheel', ev => { @@ -246,6 +261,39 @@ export class MotaRenderer extends Container implements IRenderTreeRoot { return buttons; } + private createMouseActionBase( + event: MouseEvent, + target: RenderItem = this, + mouse: MouseType = this.getMouseType(event) + ): IActionEventBase { + return { + target: target, + touch: false, + type: mouse, + buttons: this.getMouseButtons(event), + altKey: event.altKey, + ctrlKey: event.ctrlKey, + shiftKey: event.shiftKey, + metaKey: event.metaKey + }; + } + + private createTouchActionBase( + event: TouchEvent, + target: RenderItem + ): IActionEventBase { + return { + target: target, + touch: false, + type: MouseType.Left, + buttons: MouseType.Left, + altKey: event.altKey, + ctrlKey: event.ctrlKey, + shiftKey: event.shiftKey, + metaKey: event.metaKey + }; + } + private createMouseAction( event: MouseEvent, type: ActionType, @@ -385,14 +433,40 @@ export class MotaRenderer extends Container implements IRenderTreeRoot { return list; } - bubbleEvent( - type: T, - event: ActionEventMap[T] - ): ActionEventMap[T] | null { - if (this.targetCursor !== this.target.canvas.style.cursor) { - this.target.canvas.style.cursor = this.targetCursor; - } - return super.bubbleEvent(type, event); + private checkMouseEnterLeave( + event: MouseEvent, + before: Set, + now: Set + ) { + // 先 leave,再 enter + before.forEach(v => { + if (!now.has(v)) { + v.emit('leave', this.createMouseActionBase(event, v)); + } + }); + now.forEach(v => { + if (!before.has(v)) { + v.emit('enter', this.createMouseActionBase(event, v)); + } + }); + } + + private checkTouchEnterLeave( + event: TouchEvent, + before: Set, + now: Set + ) { + // 先 leave,再 enter + before.forEach(v => { + if (!now.has(v)) { + v.emit('leave', this.createTouchActionBase(event, v)); + } + }); + now.forEach(v => { + if (!before.has(v)) { + v.emit('enter', this.createTouchActionBase(event, v)); + } + }); } update(_item: RenderItem = this) { @@ -465,9 +539,10 @@ export class MotaRenderer extends Container implements IRenderTreeRoot { } hoverElement(element: RenderItem): void { - if (element.cursor !== 'auto') { + if (element.cursor !== 'inherit') { this.targetCursor = element.cursor; } + this.hoveredElement.add(element); } destroy() { diff --git a/src/core/render/renderer/elements.tsx b/src/core/render/renderer/elements.tsx index 818b070..c83ec03 100644 --- a/src/core/render/renderer/elements.tsx +++ b/src/core/render/renderer/elements.tsx @@ -76,7 +76,7 @@ type _Define

= DefineComponent< Readonly

> >; -type TagDefine = T & +export type TagDefine = T & MappingEvent & ReservedProps; diff --git a/src/core/render/renderer/index.ts b/src/core/render/renderer/index.ts index f274f93..01b41d5 100644 --- a/src/core/render/renderer/index.ts +++ b/src/core/render/renderer/index.ts @@ -8,6 +8,13 @@ import { ERenderItemEvent, RenderItem } from '../item'; import { tagMap } from './map'; import { logger } from '@/core/common/logger'; import { Comment, ETextEvent, Text } from '../preset/misc'; +import { BaseProps } from './props'; +import { TagDefine } from './elements'; + +export type DefaultProps< + P extends BaseProps = BaseProps, + E extends ERenderItemEvent = ERenderItemEvent +> = TagDefine; export const { createApp, render } = createRenderer({ patchProp: function ( diff --git a/src/core/render/renderer/props.ts b/src/core/render/renderer/props.ts index 6ffb631..5dbbd55 100644 --- a/src/core/render/renderer/props.ts +++ b/src/core/render/renderer/props.ts @@ -24,27 +24,47 @@ export interface CustomProps { } export interface BaseProps { + /** 元素的横坐标 */ x?: number; + /** 元素的纵坐标 */ y?: number; + /** 元素的横向锚点位置 */ anchorX?: number; + /** 元素的纵向锚点位置 */ anchorY?: number; + /** 元素的纵深,值越大越靠上 */ zIndex?: number; + /** 元素的宽度 */ width?: number; + /** 元素的高度 */ height?: number; + /** 元素的滤镜 */ filter?: string; + /** 是否启用高清画布 */ hd?: boolean; - antiAliasing?: boolean; + /** 是否启用抗锯齿 */ + anti?: boolean; + /** 是否不启用抗锯齿,优先级大于 anti,主要用于像素图片渲染 */ + noanti?: boolean; + /** 元素是否隐藏,可以用于一些画面效果,也可以用于调试 */ hidden?: boolean; + /** 元素的变换矩阵 */ transform?: Transform; + /** 元素的定位模式,static 表示常规定位,absolute 定位模式下元素位置始终处于左上角 */ type?: RenderItemPosition; /** 是否启用缓存,用处较少,主要用于一些默认不启用缓存的元素的特殊优化 */ cache?: boolean; /** 是否不启用缓存,优先级大于 cache,用处较少,主要用于一些特殊优化 */ nocache?: boolean; + /** 是否启用变换矩阵下穿,下穿模式下,当前元素会使用由父元素传递过来的变换矩阵,而非元素自身的 */ fall?: boolean; + /** 这个元素的唯一标识符,不可重复 */ id?: string; + /** 这个元素的不透明度 */ alpha?: number; + /** 这个元素与已渲染内容的混合模式,默认为 source-over */ composite?: GlobalCompositeOperation; + /** 鼠标放在这个元素上时的光标样式 */ cursor?: string; /** * 定位属性,可以填 `[横坐标,纵坐标,宽度,高度,x锚点,y锚点]`, diff --git a/src/core/render/sprite.ts b/src/core/render/sprite.ts index db8c5e9..4e41a22 100644 --- a/src/core/render/sprite.ts +++ b/src/core/render/sprite.ts @@ -6,7 +6,6 @@ import { } from './item'; import { MotaOffscreenCanvas2D } from '../fx/canvas2d'; import { Transform } from './transform'; -import { ElementNamespace, ComponentInternalInstance } from 'vue'; export interface ESpriteEvent extends ERenderItemEvent {} @@ -42,19 +41,17 @@ export class Sprite< this.update(this); } - patchProp( + protected handleProps( key: string, - prevValue: any, - nextValue: any, - namespace?: ElementNamespace, - parentComponent?: ComponentInternalInstance | null - ): void { + _prevValue: any, + nextValue: any + ): boolean { switch (key) { case 'render': - if (!this.assertType(nextValue, 'function', key)) return; + if (!this.assertType(nextValue, 'function', key)) return false; this.setRenderFn(nextValue); - break; + return true; } - super.patchProp(key, prevValue, nextValue, namespace, parentComponent); + return false; } } diff --git a/src/module/render/components/misc.tsx b/src/module/render/components/misc.tsx index e9f9991..6073e2d 100644 --- a/src/module/render/components/misc.tsx +++ b/src/module/render/components/misc.tsx @@ -1,9 +1,9 @@ -import { ElementLocator, Sprite } from '@/core/render'; +import { DefaultProps, ElementLocator, Sprite } from '@/core/render'; import { defineComponent, ref, watch } from 'vue'; import { SetupComponentOptions } from './types'; import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d'; -interface ProgressProps { +interface ProgressProps extends DefaultProps { /** 进度条的位置 */ loc: ElementLocator; /** 进度条的进度,1表示完成,0表示未完成 */ diff --git a/src/module/render/components/page.tsx b/src/module/render/components/page.tsx index 0903736..2435b3d 100644 --- a/src/module/render/components/page.tsx +++ b/src/module/render/components/page.tsx @@ -10,12 +10,12 @@ import { } from 'vue'; import { SetupComponentOptions } from './types'; import { clamp } from 'lodash-es'; -import { ElementLocator } from '@/core/render'; +import { DefaultProps, ElementLocator } from '@/core/render'; /** 圆角矩形页码距离容器的边框大小,与 pageSize 相乘 */ const RECT_PAD = 0.1; -export interface PageProps { +export interface PageProps extends DefaultProps { /** 共有多少页 */ pages: number; /** 页码组件的定位 */ @@ -40,6 +40,23 @@ const pageProps = { props: ['pages', 'loc', 'pageSize'] } satisfies SetupComponentOptions; +/** + * 分页组件,用于多页切换,例如存档界面等。参数参考 {@link PageProps},函数接口参考 {@link PageExpose} + * + * --- + * + * 用例如下,是一个在每页显示文字的用例,其中 page 表示第几页: + * ```tsx + * + * { + * (page: number) => { + * // 页码从第一页开始,因此这里索引要减一 + * return items[page - 1].map(v => ) + * } + * } + * + * ``` + */ export const Page = defineComponent( (props, { slots, expose }) => { const nowPage = ref(1); @@ -60,8 +77,8 @@ export const Page = defineComponent( const textLoc = ref([0, 0, 0, 0]); // 两个监听的参数 - const leftArrow = ref(new Path2D()); - const rightArrow = ref(new Path2D()); + const leftArrow = ref(); + const rightArrow = ref(); const isFirst = computed(() => nowPage.value === 1); const isLast = computed(() => nowPage.value === props.pages); diff --git a/src/module/render/components/scroll.tsx b/src/module/render/components/scroll.tsx index 0e18fde..1780258 100644 --- a/src/module/render/components/scroll.tsx +++ b/src/module/render/components/scroll.tsx @@ -13,6 +13,7 @@ import { import { SetupComponentOptions } from './types'; import { Container, + DefaultProps, ElementLocator, RenderItem, Sprite, @@ -38,7 +39,7 @@ export interface ScrollExpose { scrollTo(y: number, time?: number): void; } -export interface ScrollProps { +export interface ScrollProps extends DefaultProps { loc: ElementLocator; hor?: boolean; noscroll?: boolean; diff --git a/src/module/render/components/textbox.tsx b/src/module/render/components/textbox.tsx index 6afb6ba..8754407 100644 --- a/src/module/render/components/textbox.tsx +++ b/src/module/render/components/textbox.tsx @@ -12,12 +12,12 @@ import { watch } from 'vue'; import { logger } from '@/core/common/logger'; -import { Sprite } from '../../../core/render/sprite'; -import { ContainerProps } from '../../../core/render/renderer'; +import { Sprite } from '@/core/render/sprite'; +import { ContainerProps, DefaultProps } from '@/core/render/renderer'; import { isNil } from 'lodash-es'; import { SetupComponentOptions } from './types'; import EventEmitter from 'eventemitter3'; -import { Text } from '../../../core/render/preset'; +import { Text } from '@/core/render/preset'; import { ITextContentConfig, TextContentTyper, @@ -26,7 +26,7 @@ import { } from './textboxTyper'; export interface TextContentProps - extends ContainerProps, + extends DefaultProps, Partial { /** 显示的文字 */ text?: string; diff --git a/src/module/render/components/textboxTyper.ts b/src/module/render/components/textboxTyper.ts index e884d6e..0b7fa76 100644 --- a/src/module/render/components/textboxTyper.ts +++ b/src/module/render/components/textboxTyper.ts @@ -1125,8 +1125,6 @@ export class TextContentParser { this.checkRestLine(width, guess); } - console.log(this.renderable); - return { lineHeights: this.lineHeights, data: this.renderable