mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-04-18 17:48:52 +08:00
refactor: enter 和 leave 事件 & patchProp 实现
This commit is contained in:
parent
73acde7f49
commit
91e448fdcc
@ -1,4 +1,3 @@
|
|||||||
import { ElementNamespace, ComponentInternalInstance } from 'vue';
|
|
||||||
import { MotaOffscreenCanvas2D } from '../fx/canvas2d';
|
import { MotaOffscreenCanvas2D } from '../fx/canvas2d';
|
||||||
import { ActionType, EventProgress, ActionEventMap } from './event';
|
import { ActionType, EventProgress, ActionEventMap } from './event';
|
||||||
import {
|
import {
|
||||||
@ -168,20 +167,18 @@ export class ContainerCustom extends Container {
|
|||||||
this.renderFn = render;
|
this.renderFn = render;
|
||||||
}
|
}
|
||||||
|
|
||||||
patchProp(
|
protected handleProps(
|
||||||
key: string,
|
key: string,
|
||||||
prevValue: any,
|
prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'render': {
|
case 'render': {
|
||||||
if (!this.assertType(nextValue, 'function', key)) return;
|
if (!this.assertType(nextValue, 'function', key)) return false;
|
||||||
this.setRenderFn(nextValue);
|
this.setRenderFn(nextValue);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.patchProp(key, prevValue, nextValue, namespace, parentComponent);
|
return super.handleProps(key, prevValue, nextValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,21 +49,11 @@ export const enum EventProgress {
|
|||||||
Bubble
|
Bubble
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IActionEvent {
|
export interface IActionEventBase {
|
||||||
/** 当前事件是监听的哪个元素 */
|
/** 当前事件是监听的哪个元素 */
|
||||||
target: RenderItem;
|
target: RenderItem;
|
||||||
/** 这次操作的标识符,在按下、移动、抬起阶段中保持不变 */
|
|
||||||
identifier: number;
|
|
||||||
/** 是触摸操作还是鼠标操作 */
|
/** 是触摸操作还是鼠标操作 */
|
||||||
touch: boolean;
|
touch: boolean;
|
||||||
/** 相对于触发元素左上角的横坐标 */
|
|
||||||
offsetX: number;
|
|
||||||
/** 相对于触发元素左上角的纵坐标 */
|
|
||||||
offsetY: number;
|
|
||||||
/** 相对于整个画布左上角的横坐标 */
|
|
||||||
absoluteX: number;
|
|
||||||
/** 相对于整个画布左上角的纵坐标 */
|
|
||||||
absoluteY: number;
|
|
||||||
/**
|
/**
|
||||||
* 触发的按键种类,会出现在点击、按下、抬起三个事件中,而其他的如移动等该值只会是 {@link MouseType.None},
|
* 触发的按键种类,会出现在点击、按下、抬起三个事件中,而其他的如移动等该值只会是 {@link MouseType.None},
|
||||||
* 电脑端可以有左键、中键、右键等,手机只会触发左键,每一项的值参考 {@link MouseType}
|
* 电脑端可以有左键、中键、右键等,手机只会触发左键,每一项的值参考 {@link MouseType}
|
||||||
@ -83,6 +73,19 @@ export interface IActionEvent {
|
|||||||
ctrlKey: boolean;
|
ctrlKey: boolean;
|
||||||
/** 触发时是否按下了 Windows(Windows) / Command(Mac) 键 */
|
/** 触发时是否按下了 Windows(Windows) / Command(Mac) 键 */
|
||||||
metaKey: boolean;
|
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<IActionEvent>];
|
upCapture: [ev: Readonly<IActionEvent>];
|
||||||
/** 当鼠标或手指在该元素上抬起的冒泡阶段触发 */
|
/** 当鼠标或手指在该元素上抬起的冒泡阶段触发 */
|
||||||
up: [ev: Readonly<IActionEvent>];
|
up: [ev: Readonly<IActionEvent>];
|
||||||
/** 当鼠标或手指进入该元素的捕获阶段触发 */
|
/** 当鼠标或手指进入该元素时触发 */
|
||||||
enterCapture: [ev: Readonly<IActionEvent>];
|
enter: [ev: Readonly<IActionEventBase>];
|
||||||
/** 当鼠标或手指进入该元素的冒泡阶段触发 */
|
/** 当鼠标或手指离开该元素时触发 */
|
||||||
enter: [ev: Readonly<IActionEvent>];
|
leave: [ev: Readonly<IActionEventBase>];
|
||||||
/** 当鼠标或手指离开该元素的捕获阶段触发 */
|
|
||||||
leaveCapture: [ev: Readonly<IActionEvent>];
|
|
||||||
/** 当鼠标或手指离开该元素的冒泡阶段触发 */
|
|
||||||
leave: [ev: Readonly<IActionEvent>];
|
|
||||||
/** 当鼠标滚轮时的捕获阶段触发 */
|
/** 当鼠标滚轮时的捕获阶段触发 */
|
||||||
wheelCapture: [ev: Readonly<IWheelEvent>];
|
wheelCapture: [ev: Readonly<IWheelEvent>];
|
||||||
/** 当鼠标滚轮时的冒泡阶段触发 */
|
/** 当鼠标滚轮时的冒泡阶段触发 */
|
||||||
@ -144,7 +143,7 @@ export interface ActionEventMap {
|
|||||||
[ActionType.Wheel]: IWheelEvent;
|
[ActionType.Wheel]: IWheelEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const eventNameMap: Record<ActionType, string> = {
|
export const eventNameMap: Record<ActionType, keyof ERenderItemActionEvent> = {
|
||||||
[ActionType.Click]: 'click',
|
[ActionType.Click]: 'click',
|
||||||
[ActionType.Down]: 'down',
|
[ActionType.Down]: 'down',
|
||||||
[ActionType.Move]: 'move',
|
[ActionType.Move]: 'move',
|
||||||
|
@ -272,7 +272,9 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
|||||||
alpha: number = 1;
|
alpha: number = 1;
|
||||||
|
|
||||||
/** 鼠标覆盖在此元素上时的光标样式 */
|
/** 鼠标覆盖在此元素上时的光标样式 */
|
||||||
cursor: string = 'auto';
|
cursor: string = 'inherit';
|
||||||
|
/** 该元素是否忽略交互事件 */
|
||||||
|
noEvent: boolean = false;
|
||||||
|
|
||||||
get x() {
|
get x() {
|
||||||
return this._transform.x;
|
return this._transform.x;
|
||||||
@ -340,14 +342,12 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
|||||||
private cachedEvent: Map<ActionType, IActionEvent> = new Map();
|
private cachedEvent: Map<ActionType, IActionEvent> = new Map();
|
||||||
/** 下穿模式下当前下穿过来的变换矩阵 */
|
/** 下穿模式下当前下穿过来的变换矩阵 */
|
||||||
private fallTransform?: Transform;
|
private fallTransform?: Transform;
|
||||||
/** 鼠标当前是否覆盖在当前元素上 */
|
|
||||||
private hovered: boolean = false;
|
|
||||||
/** 是否在元素内 */
|
/** 是否在元素内 */
|
||||||
private inElement: boolean = false;
|
private inElement: boolean = false;
|
||||||
/** 鼠标标识符映射,键为按下的鼠标按键类型,值表示本次操作的唯一标识符,在按下、移动、抬起过程中保持一致 */
|
/** 鼠标标识符映射,键为按下的鼠标按键类型,值表示本次操作的唯一标识符,在按下、移动、抬起过程中保持一致 */
|
||||||
protected mouseId: Map<MouseType, number> = new Map();
|
protected mouseId: Map<MouseType, number> = new Map();
|
||||||
/** 当前所有的触摸标识符 */
|
/** 当前所有的触摸标识符 */
|
||||||
protected touchId: Set<number> = new Set();
|
readonly touchId: Set<number> = new Set();
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
@ -650,7 +650,7 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
|||||||
|
|
||||||
//#region 父子关系
|
//#region 父子关系
|
||||||
|
|
||||||
checkRoot() {
|
checkRoot(): RenderItem | null {
|
||||||
if (this._root) return this._root;
|
if (this._root) return this._root;
|
||||||
if (this.isRoot) return this;
|
if (this.isRoot) return this;
|
||||||
let ele: RenderItem = this;
|
let ele: RenderItem = this;
|
||||||
@ -756,10 +756,12 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
|||||||
type: ActionType,
|
type: ActionType,
|
||||||
progress: EventProgress
|
progress: EventProgress
|
||||||
): keyof ERenderItemActionEvent {
|
): 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;
|
return `${eventNameMap[type]}Capture` as keyof ERenderItemActionEvent;
|
||||||
} else {
|
} else {
|
||||||
return eventNameMap[type] as keyof ERenderItemActionEvent;
|
return eventNameMap[type];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -829,6 +831,7 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
|||||||
progress: EventProgress,
|
progress: EventProgress,
|
||||||
event: ActionEventMap[T]
|
event: ActionEventMap[T]
|
||||||
): ActionEventMap[T] | null {
|
): ActionEventMap[T] | null {
|
||||||
|
if (this.noEvent) return null;
|
||||||
if (progress === EventProgress.Capture) {
|
if (progress === EventProgress.Capture) {
|
||||||
// 捕获阶段需要计算鼠标位置
|
// 捕获阶段需要计算鼠标位置
|
||||||
const tran = this.transformFallThrough
|
const tran = this.transformFallThrough
|
||||||
@ -836,7 +839,6 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
|||||||
: this._transform;
|
: this._transform;
|
||||||
if (!tran) return null;
|
if (!tran) return null;
|
||||||
const [nx, ny] = this.calActionPosition(event, tran);
|
const [nx, ny] = this.calActionPosition(event, tran);
|
||||||
|
|
||||||
const inElement = this.isActionInElement(nx, ny);
|
const inElement = this.isActionInElement(nx, ny);
|
||||||
// 在元素范围内,执行事件
|
// 在元素范围内,执行事件
|
||||||
const newEvent: ActionEventMap[T] = {
|
const newEvent: ActionEventMap[T] = {
|
||||||
@ -877,17 +879,6 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
|||||||
if (inElement) {
|
if (inElement) {
|
||||||
this._root?.hoverElement(this);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case ActionType.Down: {
|
case ActionType.Down: {
|
||||||
@ -929,10 +920,15 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
|||||||
* @returns 是否继续传递事件
|
* @returns 是否继续传递事件
|
||||||
*/
|
*/
|
||||||
protected processBubble<T extends ActionType>(
|
protected processBubble<T extends ActionType>(
|
||||||
_type: T,
|
type: T,
|
||||||
_event: ActionEventMap[T],
|
_event: ActionEventMap[T],
|
||||||
inElement: boolean
|
inElement: boolean
|
||||||
): boolean {
|
): boolean {
|
||||||
|
switch (type) {
|
||||||
|
case ActionType.Enter:
|
||||||
|
case ActionType.Leave:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return inElement;
|
return inElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1039,6 +1035,21 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
|||||||
return false;
|
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(
|
patchProp(
|
||||||
key: string,
|
key: string,
|
||||||
prevValue: any,
|
prevValue: any,
|
||||||
@ -1047,6 +1058,7 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
|||||||
_parentComponent?: ComponentInternalInstance | null
|
_parentComponent?: ComponentInternalInstance | null
|
||||||
): void {
|
): void {
|
||||||
if (isNil(prevValue) && isNil(nextValue)) return;
|
if (isNil(prevValue) && isNil(nextValue)) return;
|
||||||
|
if (this.handleProps(key, prevValue, nextValue)) return;
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'x': {
|
case 'x': {
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return;
|
||||||
@ -1093,11 +1105,16 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
|||||||
this.setHD(nextValue);
|
this.setHD(nextValue);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case 'antiAliasing': {
|
case 'anti': {
|
||||||
if (!this.assertType(nextValue, 'boolean', key)) return;
|
if (!this.assertType(nextValue, 'boolean', key)) return;
|
||||||
this.setAntiAliasing(nextValue);
|
this.setAntiAliasing(nextValue);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case 'noanti': {
|
||||||
|
if (!this.assertType(nextValue, 'boolean', key)) return;
|
||||||
|
this.setAntiAliasing(!nextValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
case 'hidden': {
|
case 'hidden': {
|
||||||
if (!this.assertType(nextValue, 'boolean', key)) return;
|
if (!this.assertType(nextValue, 'boolean', key)) return;
|
||||||
if (nextValue) this.hide();
|
if (nextValue) this.hide();
|
||||||
|
@ -18,7 +18,6 @@ import { getDamageColor } from '@/plugin/utils';
|
|||||||
import { ERenderItemEvent, RenderItem } from '../item';
|
import { ERenderItemEvent, RenderItem } from '../item';
|
||||||
import EventEmitter from 'eventemitter3';
|
import EventEmitter from 'eventemitter3';
|
||||||
import { Transform } from '../transform';
|
import { Transform } from '../transform';
|
||||||
import { ElementNamespace, ComponentInternalInstance } from 'vue';
|
|
||||||
import { transformCanvas } from '../utils';
|
import { transformCanvas } from '../utils';
|
||||||
|
|
||||||
const ensureFloorDamage = Mota.require('fn', 'ensureFloorDamage');
|
const ensureFloorDamage = Mota.require('fn', 'ensureFloorDamage');
|
||||||
@ -529,46 +528,44 @@ export class Damage extends RenderItem<EDamageEvent> {
|
|||||||
// console.timeEnd('damage');
|
// console.timeEnd('damage');
|
||||||
}
|
}
|
||||||
|
|
||||||
patchProp(
|
protected handleProps(
|
||||||
key: string,
|
key: string,
|
||||||
prevValue: any,
|
_prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'mapWidth':
|
case 'mapWidth':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setMapSize(nextValue, this.mapHeight);
|
this.setMapSize(nextValue, this.mapHeight);
|
||||||
return;
|
return true;
|
||||||
case 'mapHeight':
|
case 'mapHeight':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setMapSize(this.mapWidth, nextValue);
|
this.setMapSize(this.mapWidth, nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'cellSize':
|
case 'cellSize':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setCellSize(nextValue);
|
this.setCellSize(nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'enemy':
|
case 'enemy':
|
||||||
if (!this.assertType(nextValue, 'object', key)) return;
|
if (!this.assertType(nextValue, 'object', key)) return false;
|
||||||
this.updateCollection(nextValue);
|
this.updateCollection(nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'font':
|
case 'font':
|
||||||
if (!this.assertType(nextValue, 'string', key)) return;
|
if (!this.assertType(nextValue, 'string', key)) return false;
|
||||||
this.font = nextValue;
|
this.font = nextValue;
|
||||||
this.update();
|
this.update();
|
||||||
return;
|
return true;
|
||||||
case 'strokeStyle':
|
case 'strokeStyle':
|
||||||
this.strokeStyle = nextValue;
|
this.strokeStyle = nextValue;
|
||||||
this.update();
|
this.update();
|
||||||
return;
|
return true;
|
||||||
case 'strokeWidth':
|
case 'strokeWidth':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.strokeWidth = nextValue;
|
this.strokeWidth = nextValue;
|
||||||
this.update();
|
this.update();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
super.patchProp(key, prevValue, nextValue, namespace, parentComponent);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy(): void {
|
destroy(): void {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d';
|
import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d';
|
||||||
import { ERenderItemEvent, RenderItem } from '../item';
|
import { ERenderItemEvent, RenderItem } from '../item';
|
||||||
import { Transform } from '../transform';
|
import { Transform } from '../transform';
|
||||||
import { ElementNamespace, ComponentInternalInstance } from 'vue';
|
|
||||||
import { clamp, isNil } from 'lodash-es';
|
import { clamp, isNil } from 'lodash-es';
|
||||||
import { logger } from '@/core/common/logger';
|
import { logger } from '@/core/common/logger';
|
||||||
|
|
||||||
@ -167,15 +166,22 @@ export abstract class GraphicItemBase
|
|||||||
}
|
}
|
||||||
const path = this.cachePath;
|
const path = this.cachePath;
|
||||||
if (!path) return false;
|
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) {
|
switch (this.mode) {
|
||||||
case GraphicMode.Fill:
|
case GraphicMode.Fill:
|
||||||
return ctx.isPointInPath(path, x, y, this.fillRule);
|
return ctx.isPointInPath(path, fixX, fixY, this.fillRule);
|
||||||
case GraphicMode.Stroke:
|
case GraphicMode.Stroke:
|
||||||
|
return ctx.isPointInStroke(path, fixX, fixY);
|
||||||
case GraphicMode.FillAndStroke:
|
case GraphicMode.FillAndStroke:
|
||||||
case GraphicMode.StrokeAndFill:
|
case GraphicMode.StrokeAndFill:
|
||||||
return (
|
return (
|
||||||
ctx.isPointInPath(path, x, y, this.fillRule) ||
|
ctx.isPointInPath(path, fixX, fixY, this.fillRule) ||
|
||||||
ctx.isPointInStroke(path, x, y)
|
ctx.isPointInStroke(path, fixX, fixY)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -287,69 +293,66 @@ export abstract class GraphicItemBase
|
|||||||
ctx.miterLimit = this.miterLimit;
|
ctx.miterLimit = this.miterLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
patchProp(
|
protected handleProps(
|
||||||
key: string,
|
key: string,
|
||||||
prevValue: any,
|
_prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
if (isNil(prevValue) && isNil(nextValue)) return;
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'fill':
|
case 'fill':
|
||||||
if (!this.assertType(nextValue, 'boolean', key)) return;
|
if (!this.assertType(nextValue, 'boolean', key)) return false;
|
||||||
this.checkMode(GraphicModeProp.Fill, nextValue);
|
this.checkMode(GraphicModeProp.Fill, nextValue);
|
||||||
break;
|
return true;
|
||||||
case 'stroke':
|
case 'stroke':
|
||||||
if (!this.assertType(nextValue, 'boolean', key)) return;
|
if (!this.assertType(nextValue, 'boolean', key)) return false;
|
||||||
this.checkMode(GraphicModeProp.Stroke, nextValue);
|
this.checkMode(GraphicModeProp.Stroke, nextValue);
|
||||||
break;
|
return true;
|
||||||
case 'strokeAndFill':
|
case 'strokeAndFill':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.checkMode(GraphicModeProp.StrokeAndFill, nextValue);
|
this.checkMode(GraphicModeProp.StrokeAndFill, nextValue);
|
||||||
break;
|
return true;
|
||||||
case 'fillRule':
|
case 'fillRule':
|
||||||
if (!this.assertType(nextValue, 'string', key)) return;
|
if (!this.assertType(nextValue, 'string', key)) return false;
|
||||||
this.setFillRule(nextValue);
|
this.setFillRule(nextValue);
|
||||||
break;
|
return true;
|
||||||
case 'fillStyle':
|
case 'fillStyle':
|
||||||
this.setFillStyle(nextValue);
|
this.setFillStyle(nextValue);
|
||||||
break;
|
return true;
|
||||||
case 'strokeStyle':
|
case 'strokeStyle':
|
||||||
this.setStrokeStyle(nextValue);
|
this.setStrokeStyle(nextValue);
|
||||||
break;
|
return true;
|
||||||
case 'lineWidth':
|
case 'lineWidth':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.lineWidth = nextValue;
|
this.lineWidth = nextValue;
|
||||||
this.update();
|
this.update();
|
||||||
break;
|
return true;
|
||||||
case 'lineDash':
|
case 'lineDash':
|
||||||
if (!this.assertType(nextValue, Array, key)) return;
|
if (!this.assertType(nextValue, Array, key)) return false;
|
||||||
this.lineDash = nextValue as number[];
|
this.lineDash = nextValue as number[];
|
||||||
this.update();
|
this.update();
|
||||||
break;
|
return true;
|
||||||
case 'lineDashOffset':
|
case 'lineDashOffset':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.lineDashOffset = nextValue;
|
this.lineDashOffset = nextValue;
|
||||||
this.update();
|
this.update();
|
||||||
break;
|
return true;
|
||||||
case 'lineJoin':
|
case 'lineJoin':
|
||||||
if (!this.assertType(nextValue, 'string', key)) return;
|
if (!this.assertType(nextValue, 'string', key)) return false;
|
||||||
this.lineJoin = nextValue;
|
this.lineJoin = nextValue;
|
||||||
this.update();
|
this.update();
|
||||||
break;
|
return true;
|
||||||
case 'lineCap':
|
case 'lineCap':
|
||||||
if (!this.assertType(nextValue, 'string', key)) return;
|
if (!this.assertType(nextValue, 'string', key)) return false;
|
||||||
this.lineCap = nextValue;
|
this.lineCap = nextValue;
|
||||||
this.update();
|
this.update();
|
||||||
break;
|
return true;
|
||||||
case 'miterLimit':
|
case 'miterLimit':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.miterLimit = nextValue;
|
this.miterLimit = nextValue;
|
||||||
this.update();
|
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();
|
this.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
patchProp(
|
protected handleProps(
|
||||||
key: string,
|
key: string,
|
||||||
prevValue: any,
|
prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'radius':
|
case 'radius':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setRadius(nextValue);
|
this.setRadius(nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'start':
|
case 'start':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setAngle(nextValue, this.end);
|
this.setAngle(nextValue, this.end);
|
||||||
return;
|
return true;
|
||||||
case 'end':
|
case 'end':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setAngle(this.start, nextValue);
|
this.setAngle(this.start, nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'circle': {
|
case 'circle': {
|
||||||
const value = nextValue as CircleParams;
|
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;
|
const [cx, cy, radius, start, end] = value;
|
||||||
if (!isNil(cx) && !isNil(cy)) {
|
if (!isNil(cx) && !isNil(cy)) {
|
||||||
this.pos(cx, cy);
|
this.pos(cx, cy);
|
||||||
@ -440,10 +441,10 @@ export class Circle extends GraphicItemBase {
|
|||||||
if (!isNil(start) && !isNil(end)) {
|
if (!isNil(start) && !isNil(end)) {
|
||||||
this.setAngle(start, 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();
|
this.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
patchProp(
|
protected handleProps(
|
||||||
key: string,
|
key: string,
|
||||||
prevValue: any,
|
prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'radiusX':
|
case 'radiusX':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setRadius(nextValue, this.radiusY);
|
this.setRadius(nextValue, this.radiusY);
|
||||||
return;
|
return true;
|
||||||
case 'radiusY':
|
case 'radiusY':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setRadius(this.radiusY, nextValue);
|
this.setRadius(this.radiusY, nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'start':
|
case 'start':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setAngle(nextValue, this.end);
|
this.setAngle(nextValue, this.end);
|
||||||
return;
|
return true;
|
||||||
case 'end':
|
case 'end':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setAngle(this.start, nextValue);
|
this.setAngle(this.start, nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'ellipse': {
|
case 'ellipse': {
|
||||||
const value = nextValue as EllipseParams;
|
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;
|
const [cx, cy, radiusX, radiusY, start, end] = value;
|
||||||
if (!isNil(cx) && !isNil(cy)) {
|
if (!isNil(cx) && !isNil(cy)) {
|
||||||
this.pos(cx, cy);
|
this.pos(cx, cy);
|
||||||
@ -531,10 +530,10 @@ export class Ellipse extends GraphicItemBase {
|
|||||||
if (!isNil(start) && !isNil(end)) {
|
if (!isNil(start) && !isNil(end)) {
|
||||||
this.setAngle(start, 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;
|
this.pathDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
patchProp(
|
protected handleProps(
|
||||||
key: string,
|
key: string,
|
||||||
prevValue: any,
|
prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'x1':
|
case 'x1':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setPoint1(nextValue, this.y1);
|
this.setPoint1(nextValue, this.y1);
|
||||||
return;
|
return true;
|
||||||
case 'y1':
|
case 'y1':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setPoint1(this.x1, nextValue);
|
this.setPoint1(this.x1, nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'x2':
|
case 'x2':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setPoint2(nextValue, this.y2);
|
this.setPoint2(nextValue, this.y2);
|
||||||
return;
|
return true;
|
||||||
case 'y2':
|
case 'y2':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setPoint2(this.x2, nextValue);
|
this.setPoint2(this.x2, nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'line':
|
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.setPoint1(nextValue[0], nextValue[1]);
|
||||||
this.setPoint2(nextValue[2], nextValue[3]);
|
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();
|
this.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected isActionInElement(x: number, y: number): boolean {
|
||||||
|
return x >= 0 && x < this.width && y >= 0 && y < this.height;
|
||||||
|
}
|
||||||
|
|
||||||
private fitRect() {
|
private fitRect() {
|
||||||
const left = Math.min(this.sx, this.cp1x, this.cp2x, this.ex);
|
const left = Math.min(this.sx, this.cp1x, this.cp2x, this.ex);
|
||||||
const top = Math.min(this.sy, this.cp1y, this.cp2y, this.ey);
|
const top = Math.min(this.sy, this.cp1y, this.cp2y, this.ey);
|
||||||
@ -695,55 +698,55 @@ export class BezierCurve extends GraphicItemBase {
|
|||||||
this.pathDirty = true;
|
this.pathDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
patchProp(
|
protected handleProps(
|
||||||
key: string,
|
key: string,
|
||||||
prevValue: any,
|
prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'sx':
|
case 'sx':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setStart(nextValue, this.sy);
|
this.setStart(nextValue, this.sy);
|
||||||
return;
|
return true;
|
||||||
case 'sy':
|
case 'sy':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setStart(this.sx, nextValue);
|
this.setStart(this.sx, nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'cp1x':
|
case 'cp1x':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setControl1(nextValue, this.cp1y);
|
this.setControl1(nextValue, this.cp1y);
|
||||||
return;
|
return true;
|
||||||
case 'cp1y':
|
case 'cp1y':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setControl1(this.cp1x, nextValue);
|
this.setControl1(this.cp1x, nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'cp2x':
|
case 'cp2x':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setControl2(nextValue, this.cp2y);
|
this.setControl2(nextValue, this.cp2y);
|
||||||
return;
|
return true;
|
||||||
case 'cp2y':
|
case 'cp2y':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setControl2(this.cp2x, nextValue);
|
this.setControl2(this.cp2x, nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'ex':
|
case 'ex':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setEnd(nextValue, this.ey);
|
this.setEnd(nextValue, this.ey);
|
||||||
return;
|
return true;
|
||||||
case 'ey':
|
case 'ey':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setEnd(this.ex, nextValue);
|
this.setEnd(this.ex, nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'curve':
|
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.setStart(nextValue[0], nextValue[1]);
|
||||||
this.setControl1(nextValue[2], nextValue[3]);
|
this.setControl1(nextValue[2], nextValue[3]);
|
||||||
this.setControl2(nextValue[4], nextValue[5]);
|
this.setControl2(nextValue[4], nextValue[5]);
|
||||||
this.setEnd(nextValue[6], nextValue[7]);
|
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;
|
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,
|
key: string,
|
||||||
prevValue: any,
|
prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'sx':
|
case 'sx':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setStart(nextValue, this.sy);
|
this.setStart(nextValue, this.sy);
|
||||||
return;
|
return true;
|
||||||
case 'sy':
|
case 'sy':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setStart(this.sx, nextValue);
|
this.setStart(this.sx, nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'cpx':
|
case 'cpx':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setControl(nextValue, this.cpy);
|
this.setControl(nextValue, this.cpy);
|
||||||
return;
|
return true;
|
||||||
case 'cpy':
|
case 'cpy':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setControl(this.cpx, nextValue);
|
this.setControl(this.cpx, nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'ex':
|
case 'ex':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setEnd(nextValue, this.ey);
|
this.setEnd(nextValue, this.ey);
|
||||||
return;
|
return true;
|
||||||
case 'ey':
|
case 'ey':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setEnd(this.ex, nextValue);
|
this.setEnd(this.ex, nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'curve':
|
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.setStart(nextValue[0], nextValue[1]);
|
||||||
this.setControl(nextValue[2], nextValue[3]);
|
this.setControl(nextValue[2], nextValue[3]);
|
||||||
this.setEnd(nextValue[4], nextValue[5]);
|
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();
|
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,
|
key: string,
|
||||||
prevValue: any,
|
prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'path':
|
case 'path':
|
||||||
if (!this.assertType(nextValue, Path2D, key)) return;
|
if (!this.assertType(nextValue, Path2D, key)) return false;
|
||||||
this.path = nextValue;
|
this.path = nextValue;
|
||||||
this.pathDirty = true;
|
this.pathDirty = true;
|
||||||
this.update();
|
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,
|
key: string,
|
||||||
prevValue: any,
|
prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'circle': {
|
case 'circle': {
|
||||||
const value = nextValue as RectRCircleParams;
|
const value = nextValue as RectRCircleParams;
|
||||||
if (!this.assertType(value, Array, key)) return;
|
if (!this.assertType(value, Array, key)) return false;
|
||||||
this.setCircle(value);
|
this.setCircle(value);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
case 'ellipse': {
|
case 'ellipse': {
|
||||||
const value = nextValue as RectREllipseParams;
|
const value = nextValue as RectREllipseParams;
|
||||||
if (!this.assertType(value, Array, key)) return;
|
if (!this.assertType(value, Array, key)) return false;
|
||||||
this.setEllipse(value);
|
this.setEllipse(value);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.patchProp(key, prevValue, nextValue, namespace, parentComponent);
|
return super.handleProps(key, prevValue, nextValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import { BlockCacher, CanvasCacheItem, ICanvasCacheItem } from './block';
|
|||||||
import { Transform } from '../transform';
|
import { Transform } from '../transform';
|
||||||
import { LayerFloorBinder, LayerGroupFloorBinder } from './floor';
|
import { LayerFloorBinder, LayerGroupFloorBinder } from './floor';
|
||||||
import { RenderAdapter } from '../adapter';
|
import { RenderAdapter } from '../adapter';
|
||||||
import { ElementNamespace, ComponentInternalInstance } from 'vue';
|
|
||||||
import { IAnimateFrame, renderEmits } from '../frame';
|
import { IAnimateFrame, renderEmits } from '../frame';
|
||||||
|
|
||||||
export interface ILayerGroupRenderExtends {
|
export interface ILayerGroupRenderExtends {
|
||||||
@ -332,36 +331,34 @@ export class LayerGroup
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
patchProp(
|
protected handleProps(
|
||||||
key: string,
|
key: string,
|
||||||
prevValue: any,
|
_prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'cellSize':
|
case 'cellSize':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setCellSize(nextValue);
|
this.setCellSize(nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'blockSize':
|
case 'blockSize':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setBlockSize(nextValue);
|
this.setBlockSize(nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'floorId': {
|
case 'floorId': {
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
const binder = this.getExtends('floor-binder');
|
const binder = this.getExtends('floor-binder');
|
||||||
if (binder instanceof LayerGroupFloorBinder) {
|
if (binder instanceof LayerGroupFloorBinder) {
|
||||||
binder.bindFloor(nextValue);
|
binder.bindFloor(nextValue);
|
||||||
}
|
}
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
case 'camera':
|
case 'camera':
|
||||||
if (!this.assertType(nextValue, Transform, key)) return;
|
if (!this.assertType(nextValue, Transform, key)) return false;
|
||||||
this.camera = nextValue;
|
this.camera = nextValue;
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
super.patchProp(key, prevValue, nextValue, namespace, parentComponent);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy(): void {
|
destroy(): void {
|
||||||
@ -1438,16 +1435,14 @@ export class Layer extends Container<ELayerEvent> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
patchProp(
|
protected handleProps(
|
||||||
key: string,
|
key: string,
|
||||||
prevValue: any,
|
_prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'layer': {
|
case 'layer': {
|
||||||
if (!this.assertType(nextValue, 'string', key)) return;
|
if (!this.assertType(nextValue, 'string', key)) return false;
|
||||||
const parent = this.parent;
|
const parent = this.parent;
|
||||||
if (parent instanceof LayerGroup) {
|
if (parent instanceof LayerGroup) {
|
||||||
parent.removeLayer(this);
|
parent.removeLayer(this);
|
||||||
@ -1457,30 +1452,30 @@ export class Layer extends Container<ELayerEvent> {
|
|||||||
this.layer = nextValue;
|
this.layer = nextValue;
|
||||||
}
|
}
|
||||||
this.update();
|
this.update();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
case 'cellSize':
|
case 'cellSize':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setCellSize(nextValue);
|
this.setCellSize(nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'mapWidth':
|
case 'mapWidth':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setMapSize(nextValue, this.mapHeight);
|
this.setMapSize(nextValue, this.mapHeight);
|
||||||
return;
|
return true;
|
||||||
case 'mapHeight':
|
case 'mapHeight':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setMapSize(this.mapWidth, nextValue);
|
this.setMapSize(this.mapWidth, nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'background':
|
case 'background':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setBackground(nextValue);
|
this.setBackground(nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'floorImage':
|
case 'floorImage':
|
||||||
if (!this.assertType(nextValue, Array, key)) return;
|
if (!this.assertType(nextValue, Array, key)) return false;
|
||||||
this.setFloorImage(nextValue as FloorAnimate[]);
|
this.setFloorImage(nextValue as FloorAnimate[]);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
super.patchProp(key, prevValue, nextValue, namespace, parentComponent);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private addToGroup(group: LayerGroup) {
|
private addToGroup(group: LayerGroup) {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d';
|
import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d';
|
||||||
import { ERenderItemEvent, RenderItem, RenderItemPosition } from '../item';
|
import { ERenderItemEvent, RenderItem, RenderItemPosition } from '../item';
|
||||||
import { Transform } from '../transform';
|
import { Transform } from '../transform';
|
||||||
import { ElementNamespace, ComponentInternalInstance } from 'vue';
|
|
||||||
import { AutotileRenderable, RenderableData } from '../cache';
|
import { AutotileRenderable, RenderableData } from '../cache';
|
||||||
import { texture } from '../cache';
|
import { texture } from '../cache';
|
||||||
import { isNil } from 'lodash-es';
|
import { isNil } from 'lodash-es';
|
||||||
@ -114,33 +113,31 @@ export class Text extends RenderItem<ETextEvent> {
|
|||||||
this.size(width, actualBoundingBoxAscent + actualBoundingBoxDescent);
|
this.size(width, actualBoundingBoxAscent + actualBoundingBoxDescent);
|
||||||
}
|
}
|
||||||
|
|
||||||
patchProp(
|
protected handleProps(
|
||||||
key: string,
|
key: string,
|
||||||
prevValue: any,
|
_prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'text':
|
case 'text':
|
||||||
if (!this.assertType(nextValue, 'string', key)) return;
|
if (!this.assertType(nextValue, 'string', key)) return false;
|
||||||
this.setText(nextValue);
|
this.setText(nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'fillStyle':
|
case 'fillStyle':
|
||||||
this.setStyle(nextValue, this.strokeStyle);
|
this.setStyle(nextValue, this.strokeStyle);
|
||||||
return;
|
return true;
|
||||||
case 'strokeStyle':
|
case 'strokeStyle':
|
||||||
this.setStyle(this.fillStyle, nextValue);
|
this.setStyle(this.fillStyle, nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'font':
|
case 'font':
|
||||||
if (!this.assertType(nextValue, 'string', key)) return;
|
if (!this.assertType(nextValue, 'string', key)) return false;
|
||||||
this.setFont(nextValue);
|
this.setFont(nextValue);
|
||||||
break;
|
break;
|
||||||
case 'strokeWidth':
|
case 'strokeWidth':
|
||||||
this.setStrokeWidth(nextValue);
|
this.setStrokeWidth(nextValue);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
super.patchProp(key, prevValue, nextValue, namespace, parentComponent);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,19 +178,17 @@ export class Image extends RenderItem<EImageEvent> {
|
|||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
patchProp(
|
protected handleProps(
|
||||||
key: string,
|
key: string,
|
||||||
prevValue: any,
|
_prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'image':
|
case 'image':
|
||||||
this.setImage(nextValue);
|
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,
|
_canvas: MotaOffscreenCanvas2D,
|
||||||
_transform: Transform
|
_transform: Transform
|
||||||
): void {}
|
): void {}
|
||||||
|
|
||||||
|
protected handleProps(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EIconEvent extends ERenderItemEvent {}
|
export interface EIconEvent extends ERenderItemEvent {}
|
||||||
@ -313,31 +312,29 @@ export class Icon extends RenderItem<EIconEvent> implements IAnimateFrame {
|
|||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
patchProp(
|
protected handleProps(
|
||||||
key: string,
|
key: string,
|
||||||
prevValue: any,
|
_prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'icon':
|
case 'icon':
|
||||||
this.setIcon(nextValue);
|
this.setIcon(nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'animate':
|
case 'animate':
|
||||||
if (!this.assertType(nextValue, 'boolean', key)) return;
|
if (!this.assertType(nextValue, 'boolean', key)) return false;
|
||||||
this.animate = nextValue;
|
this.animate = nextValue;
|
||||||
if (nextValue) renderEmits.addFramer(this);
|
if (nextValue) renderEmits.addFramer(this);
|
||||||
else renderEmits.removeFramer(this);
|
else renderEmits.removeFramer(this);
|
||||||
this.update();
|
this.update();
|
||||||
return;
|
return true;
|
||||||
case 'frame':
|
case 'frame':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.frame = nextValue;
|
this.frame = nextValue;
|
||||||
this.update();
|
this.update();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
super.patchProp(key, prevValue, nextValue, namespace, parentComponent);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,23 +541,21 @@ export class Winskin extends RenderItem<EWinskinEvent> {
|
|||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
patchProp(
|
protected handleProps(
|
||||||
key: string,
|
key: string,
|
||||||
prevValue: any,
|
_prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'image':
|
case 'image':
|
||||||
if (!this.assertType(nextValue, 'string', key)) return;
|
if (!this.assertType(nextValue, 'string', key)) return false;
|
||||||
this.setImageByName(nextValue);
|
this.setImageByName(nextValue);
|
||||||
return;
|
return true;
|
||||||
case 'borderSize':
|
case 'borderSize':
|
||||||
if (!this.assertType(nextValue, 'number', key)) return;
|
if (!this.assertType(nextValue, 'number', key)) return false;
|
||||||
this.setBorderSize(nextValue);
|
this.setBorderSize(nextValue);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
super.patchProp(key, prevValue, nextValue, namespace, parentComponent);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,9 @@ import { logger } from '../common/logger';
|
|||||||
import { MotaOffscreenCanvas2D } from '../fx/canvas2d';
|
import { MotaOffscreenCanvas2D } from '../fx/canvas2d';
|
||||||
import { Container } from './container';
|
import { Container } from './container';
|
||||||
import {
|
import {
|
||||||
ActionEventMap,
|
|
||||||
ActionType,
|
ActionType,
|
||||||
IActionEvent,
|
IActionEvent,
|
||||||
|
IActionEventBase,
|
||||||
IWheelEvent,
|
IWheelEvent,
|
||||||
MouseType,
|
MouseType,
|
||||||
WheelType
|
WheelType
|
||||||
@ -49,6 +49,10 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
|||||||
private abort?: AbortController;
|
private abort?: AbortController;
|
||||||
/** 根据捕获行为判断光标样式 */
|
/** 根据捕获行为判断光标样式 */
|
||||||
private targetCursor: string = 'auto';
|
private targetCursor: string = 'auto';
|
||||||
|
/** 当前鼠标覆盖的元素 */
|
||||||
|
private hoveredElement: Set<RenderItem> = new Set();
|
||||||
|
/** 本次交互前鼠标覆盖的元素 */
|
||||||
|
private beforeHovered: Set<RenderItem> = new Set();
|
||||||
|
|
||||||
target!: MotaOffscreenCanvas2D;
|
target!: MotaOffscreenCanvas2D;
|
||||||
|
|
||||||
@ -112,17 +116,26 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
|||||||
this.lastMouse
|
this.lastMouse
|
||||||
);
|
);
|
||||||
this.targetCursor = 'auto';
|
this.targetCursor = 'auto';
|
||||||
|
const temp = this.beforeHovered;
|
||||||
|
temp.clear();
|
||||||
|
this.beforeHovered = this.hoveredElement;
|
||||||
|
this.hoveredElement = temp;
|
||||||
this.captureEvent(ActionType.Move, event);
|
this.captureEvent(ActionType.Move, event);
|
||||||
});
|
if (this.targetCursor !== this.target.canvas.style.cursor) {
|
||||||
canvas.addEventListener('mouseenter', ev => {
|
this.target.canvas.style.cursor = this.targetCursor;
|
||||||
const event = this.createMouseAction(ev, ActionType.Enter);
|
}
|
||||||
this.emit('enterCapture', event);
|
this.checkMouseEnterLeave(
|
||||||
this.emit('enter', event);
|
ev,
|
||||||
|
this.beforeHovered,
|
||||||
|
this.hoveredElement
|
||||||
|
);
|
||||||
});
|
});
|
||||||
canvas.addEventListener('mouseleave', ev => {
|
canvas.addEventListener('mouseleave', ev => {
|
||||||
const event = this.createMouseAction(ev, ActionType.Leave);
|
this.hoveredElement.forEach(v => {
|
||||||
this.emit('leaveCapture', event);
|
v.emit('leave', this.createMouseActionBase(ev, v));
|
||||||
this.emit('leave', event);
|
});
|
||||||
|
this.hoveredElement.clear();
|
||||||
|
this.beforeHovered.clear();
|
||||||
});
|
});
|
||||||
document.addEventListener('touchstart', ev => {
|
document.addEventListener('touchstart', ev => {
|
||||||
this.createTouchAction(ev, ActionType.Down).forEach(v => {
|
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.createTouchAction(ev, ActionType.Up).forEach(v => {
|
||||||
this.captureEvent(ActionType.Up, v);
|
this.captureEvent(ActionType.Up, v);
|
||||||
this.captureEvent(ActionType.Click, v);
|
this.captureEvent(ActionType.Click, v);
|
||||||
|
this.touchInfo.delete(v.identifier);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
document.addEventListener('touchcancel', ev => {
|
document.addEventListener('touchcancel', ev => {
|
||||||
this.createTouchAction(ev, ActionType.Up).forEach(v => {
|
this.createTouchAction(ev, ActionType.Up).forEach(v => {
|
||||||
this.captureEvent(ActionType.Up, v);
|
this.captureEvent(ActionType.Up, v);
|
||||||
|
this.touchInfo.delete(v.identifier);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
document.addEventListener('touchmove', ev => {
|
document.addEventListener('touchmove', ev => {
|
||||||
this.createTouchAction(ev, ActionType.Move).forEach(v => {
|
this.createTouchAction(ev, ActionType.Move).forEach(v => {
|
||||||
const touch = this.touchInfo.get(v.identifier);
|
const touch = this.touchInfo.get(v.identifier);
|
||||||
if (!touch) return;
|
if (!touch) return;
|
||||||
const inElement = this.isTouchInCanvas(v.offsetX, v.offsetY);
|
const temp = this.beforeHovered;
|
||||||
if (touch.hovered && !inElement) {
|
temp.clear();
|
||||||
this.emit('leaveCapture', v);
|
this.beforeHovered = this.hoveredElement;
|
||||||
this.emit('leave', v);
|
this.hoveredElement = temp;
|
||||||
}
|
|
||||||
if (!touch.hovered && inElement) {
|
|
||||||
this.emit('enterCapture', v);
|
|
||||||
this.emit('enter', v);
|
|
||||||
}
|
|
||||||
this.captureEvent(ActionType.Move, v);
|
this.captureEvent(ActionType.Move, v);
|
||||||
|
this.checkTouchEnterLeave(
|
||||||
|
ev,
|
||||||
|
this.beforeHovered,
|
||||||
|
this.hoveredElement
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
canvas.addEventListener('wheel', ev => {
|
canvas.addEventListener('wheel', ev => {
|
||||||
@ -246,6 +261,39 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
|||||||
return buttons;
|
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(
|
private createMouseAction(
|
||||||
event: MouseEvent,
|
event: MouseEvent,
|
||||||
type: ActionType,
|
type: ActionType,
|
||||||
@ -385,14 +433,40 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
bubbleEvent<T extends ActionType>(
|
private checkMouseEnterLeave(
|
||||||
type: T,
|
event: MouseEvent,
|
||||||
event: ActionEventMap[T]
|
before: Set<RenderItem>,
|
||||||
): ActionEventMap[T] | null {
|
now: Set<RenderItem>
|
||||||
if (this.targetCursor !== this.target.canvas.style.cursor) {
|
) {
|
||||||
this.target.canvas.style.cursor = this.targetCursor;
|
// 先 leave,再 enter
|
||||||
}
|
before.forEach(v => {
|
||||||
return super.bubbleEvent(type, event);
|
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<RenderItem>,
|
||||||
|
now: Set<RenderItem>
|
||||||
|
) {
|
||||||
|
// 先 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) {
|
update(_item: RenderItem = this) {
|
||||||
@ -465,9 +539,10 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hoverElement(element: RenderItem): void {
|
hoverElement(element: RenderItem): void {
|
||||||
if (element.cursor !== 'auto') {
|
if (element.cursor !== 'inherit') {
|
||||||
this.targetCursor = element.cursor;
|
this.targetCursor = element.cursor;
|
||||||
}
|
}
|
||||||
|
this.hoveredElement.add(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
|
@ -76,7 +76,7 @@ type _Define<P extends BaseProps, E extends ERenderItemEvent> = DefineComponent<
|
|||||||
Readonly<P & MappingEvent<E>>
|
Readonly<P & MappingEvent<E>>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
type TagDefine<T extends object, E extends ERenderItemEvent> = T &
|
export type TagDefine<T extends object, E extends ERenderItemEvent> = T &
|
||||||
MappingEvent<E> &
|
MappingEvent<E> &
|
||||||
ReservedProps;
|
ReservedProps;
|
||||||
|
|
||||||
|
@ -8,6 +8,13 @@ import { ERenderItemEvent, RenderItem } from '../item';
|
|||||||
import { tagMap } from './map';
|
import { tagMap } from './map';
|
||||||
import { logger } from '@/core/common/logger';
|
import { logger } from '@/core/common/logger';
|
||||||
import { Comment, ETextEvent, Text } from '../preset/misc';
|
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<P, E>;
|
||||||
|
|
||||||
export const { createApp, render } = createRenderer<RenderItem, RenderItem>({
|
export const { createApp, render } = createRenderer<RenderItem, RenderItem>({
|
||||||
patchProp: function (
|
patchProp: function (
|
||||||
|
@ -24,27 +24,47 @@ export interface CustomProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface BaseProps {
|
export interface BaseProps {
|
||||||
|
/** 元素的横坐标 */
|
||||||
x?: number;
|
x?: number;
|
||||||
|
/** 元素的纵坐标 */
|
||||||
y?: number;
|
y?: number;
|
||||||
|
/** 元素的横向锚点位置 */
|
||||||
anchorX?: number;
|
anchorX?: number;
|
||||||
|
/** 元素的纵向锚点位置 */
|
||||||
anchorY?: number;
|
anchorY?: number;
|
||||||
|
/** 元素的纵深,值越大越靠上 */
|
||||||
zIndex?: number;
|
zIndex?: number;
|
||||||
|
/** 元素的宽度 */
|
||||||
width?: number;
|
width?: number;
|
||||||
|
/** 元素的高度 */
|
||||||
height?: number;
|
height?: number;
|
||||||
|
/** 元素的滤镜 */
|
||||||
filter?: string;
|
filter?: string;
|
||||||
|
/** 是否启用高清画布 */
|
||||||
hd?: boolean;
|
hd?: boolean;
|
||||||
antiAliasing?: boolean;
|
/** 是否启用抗锯齿 */
|
||||||
|
anti?: boolean;
|
||||||
|
/** 是否不启用抗锯齿,优先级大于 anti,主要用于像素图片渲染 */
|
||||||
|
noanti?: boolean;
|
||||||
|
/** 元素是否隐藏,可以用于一些画面效果,也可以用于调试 */
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
|
/** 元素的变换矩阵 */
|
||||||
transform?: Transform;
|
transform?: Transform;
|
||||||
|
/** 元素的定位模式,static 表示常规定位,absolute 定位模式下元素位置始终处于左上角 */
|
||||||
type?: RenderItemPosition;
|
type?: RenderItemPosition;
|
||||||
/** 是否启用缓存,用处较少,主要用于一些默认不启用缓存的元素的特殊优化 */
|
/** 是否启用缓存,用处较少,主要用于一些默认不启用缓存的元素的特殊优化 */
|
||||||
cache?: boolean;
|
cache?: boolean;
|
||||||
/** 是否不启用缓存,优先级大于 cache,用处较少,主要用于一些特殊优化 */
|
/** 是否不启用缓存,优先级大于 cache,用处较少,主要用于一些特殊优化 */
|
||||||
nocache?: boolean;
|
nocache?: boolean;
|
||||||
|
/** 是否启用变换矩阵下穿,下穿模式下,当前元素会使用由父元素传递过来的变换矩阵,而非元素自身的 */
|
||||||
fall?: boolean;
|
fall?: boolean;
|
||||||
|
/** 这个元素的唯一标识符,不可重复 */
|
||||||
id?: string;
|
id?: string;
|
||||||
|
/** 这个元素的不透明度 */
|
||||||
alpha?: number;
|
alpha?: number;
|
||||||
|
/** 这个元素与已渲染内容的混合模式,默认为 source-over */
|
||||||
composite?: GlobalCompositeOperation;
|
composite?: GlobalCompositeOperation;
|
||||||
|
/** 鼠标放在这个元素上时的光标样式 */
|
||||||
cursor?: string;
|
cursor?: string;
|
||||||
/**
|
/**
|
||||||
* 定位属性,可以填 `[横坐标,纵坐标,宽度,高度,x锚点,y锚点]`,
|
* 定位属性,可以填 `[横坐标,纵坐标,宽度,高度,x锚点,y锚点]`,
|
||||||
|
@ -6,7 +6,6 @@ import {
|
|||||||
} from './item';
|
} from './item';
|
||||||
import { MotaOffscreenCanvas2D } from '../fx/canvas2d';
|
import { MotaOffscreenCanvas2D } from '../fx/canvas2d';
|
||||||
import { Transform } from './transform';
|
import { Transform } from './transform';
|
||||||
import { ElementNamespace, ComponentInternalInstance } from 'vue';
|
|
||||||
|
|
||||||
export interface ESpriteEvent extends ERenderItemEvent {}
|
export interface ESpriteEvent extends ERenderItemEvent {}
|
||||||
|
|
||||||
@ -42,19 +41,17 @@ export class Sprite<
|
|||||||
this.update(this);
|
this.update(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
patchProp(
|
protected handleProps(
|
||||||
key: string,
|
key: string,
|
||||||
prevValue: any,
|
_prevValue: any,
|
||||||
nextValue: any,
|
nextValue: any
|
||||||
namespace?: ElementNamespace,
|
): boolean {
|
||||||
parentComponent?: ComponentInternalInstance | null
|
|
||||||
): void {
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'render':
|
case 'render':
|
||||||
if (!this.assertType(nextValue, 'function', key)) return;
|
if (!this.assertType(nextValue, 'function', key)) return false;
|
||||||
this.setRenderFn(nextValue);
|
this.setRenderFn(nextValue);
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
super.patchProp(key, prevValue, nextValue, namespace, parentComponent);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { ElementLocator, Sprite } from '@/core/render';
|
import { DefaultProps, ElementLocator, Sprite } from '@/core/render';
|
||||||
import { defineComponent, ref, watch } from 'vue';
|
import { defineComponent, ref, watch } from 'vue';
|
||||||
import { SetupComponentOptions } from './types';
|
import { SetupComponentOptions } from './types';
|
||||||
import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d';
|
import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d';
|
||||||
|
|
||||||
interface ProgressProps {
|
interface ProgressProps extends DefaultProps {
|
||||||
/** 进度条的位置 */
|
/** 进度条的位置 */
|
||||||
loc: ElementLocator;
|
loc: ElementLocator;
|
||||||
/** 进度条的进度,1表示完成,0表示未完成 */
|
/** 进度条的进度,1表示完成,0表示未完成 */
|
||||||
|
@ -10,12 +10,12 @@ import {
|
|||||||
} from 'vue';
|
} from 'vue';
|
||||||
import { SetupComponentOptions } from './types';
|
import { SetupComponentOptions } from './types';
|
||||||
import { clamp } from 'lodash-es';
|
import { clamp } from 'lodash-es';
|
||||||
import { ElementLocator } from '@/core/render';
|
import { DefaultProps, ElementLocator } from '@/core/render';
|
||||||
|
|
||||||
/** 圆角矩形页码距离容器的边框大小,与 pageSize 相乘 */
|
/** 圆角矩形页码距离容器的边框大小,与 pageSize 相乘 */
|
||||||
const RECT_PAD = 0.1;
|
const RECT_PAD = 0.1;
|
||||||
|
|
||||||
export interface PageProps {
|
export interface PageProps extends DefaultProps {
|
||||||
/** 共有多少页 */
|
/** 共有多少页 */
|
||||||
pages: number;
|
pages: number;
|
||||||
/** 页码组件的定位 */
|
/** 页码组件的定位 */
|
||||||
@ -40,6 +40,23 @@ const pageProps = {
|
|||||||
props: ['pages', 'loc', 'pageSize']
|
props: ['pages', 'loc', 'pageSize']
|
||||||
} satisfies SetupComponentOptions<PageProps, {}, string, PageSlots>;
|
} satisfies SetupComponentOptions<PageProps, {}, string, PageSlots>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页组件,用于多页切换,例如存档界面等。参数参考 {@link PageProps},函数接口参考 {@link PageExpose}
|
||||||
|
*
|
||||||
|
* ---
|
||||||
|
*
|
||||||
|
* 用例如下,是一个在每页显示文字的用例,其中 page 表示第几页:
|
||||||
|
* ```tsx
|
||||||
|
* <Page maxPage={5}>
|
||||||
|
* {
|
||||||
|
* (page: number) => {
|
||||||
|
* // 页码从第一页开始,因此这里索引要减一
|
||||||
|
* return items[page - 1].map(v => <text text={v.text} />)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </Page>
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
export const Page = defineComponent<PageProps, {}, string, PageSlots>(
|
export const Page = defineComponent<PageProps, {}, string, PageSlots>(
|
||||||
(props, { slots, expose }) => {
|
(props, { slots, expose }) => {
|
||||||
const nowPage = ref(1);
|
const nowPage = ref(1);
|
||||||
@ -60,8 +77,8 @@ export const Page = defineComponent<PageProps, {}, string, PageSlots>(
|
|||||||
const textLoc = ref<ElementLocator>([0, 0, 0, 0]);
|
const textLoc = ref<ElementLocator>([0, 0, 0, 0]);
|
||||||
|
|
||||||
// 两个监听的参数
|
// 两个监听的参数
|
||||||
const leftArrow = ref<Path2D>(new Path2D());
|
const leftArrow = ref<Path2D>();
|
||||||
const rightArrow = ref<Path2D>(new Path2D());
|
const rightArrow = ref<Path2D>();
|
||||||
|
|
||||||
const isFirst = computed(() => nowPage.value === 1);
|
const isFirst = computed(() => nowPage.value === 1);
|
||||||
const isLast = computed(() => nowPage.value === props.pages);
|
const isLast = computed(() => nowPage.value === props.pages);
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
import { SetupComponentOptions } from './types';
|
import { SetupComponentOptions } from './types';
|
||||||
import {
|
import {
|
||||||
Container,
|
Container,
|
||||||
|
DefaultProps,
|
||||||
ElementLocator,
|
ElementLocator,
|
||||||
RenderItem,
|
RenderItem,
|
||||||
Sprite,
|
Sprite,
|
||||||
@ -38,7 +39,7 @@ export interface ScrollExpose {
|
|||||||
scrollTo(y: number, time?: number): void;
|
scrollTo(y: number, time?: number): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ScrollProps {
|
export interface ScrollProps extends DefaultProps {
|
||||||
loc: ElementLocator;
|
loc: ElementLocator;
|
||||||
hor?: boolean;
|
hor?: boolean;
|
||||||
noscroll?: boolean;
|
noscroll?: boolean;
|
||||||
|
@ -12,12 +12,12 @@ import {
|
|||||||
watch
|
watch
|
||||||
} from 'vue';
|
} from 'vue';
|
||||||
import { logger } from '@/core/common/logger';
|
import { logger } from '@/core/common/logger';
|
||||||
import { Sprite } from '../../../core/render/sprite';
|
import { Sprite } from '@/core/render/sprite';
|
||||||
import { ContainerProps } from '../../../core/render/renderer';
|
import { ContainerProps, DefaultProps } from '@/core/render/renderer';
|
||||||
import { isNil } from 'lodash-es';
|
import { isNil } from 'lodash-es';
|
||||||
import { SetupComponentOptions } from './types';
|
import { SetupComponentOptions } from './types';
|
||||||
import EventEmitter from 'eventemitter3';
|
import EventEmitter from 'eventemitter3';
|
||||||
import { Text } from '../../../core/render/preset';
|
import { Text } from '@/core/render/preset';
|
||||||
import {
|
import {
|
||||||
ITextContentConfig,
|
ITextContentConfig,
|
||||||
TextContentTyper,
|
TextContentTyper,
|
||||||
@ -26,7 +26,7 @@ import {
|
|||||||
} from './textboxTyper';
|
} from './textboxTyper';
|
||||||
|
|
||||||
export interface TextContentProps
|
export interface TextContentProps
|
||||||
extends ContainerProps,
|
extends DefaultProps,
|
||||||
Partial<ITextContentConfig> {
|
Partial<ITextContentConfig> {
|
||||||
/** 显示的文字 */
|
/** 显示的文字 */
|
||||||
text?: string;
|
text?: string;
|
||||||
|
@ -1125,8 +1125,6 @@ export class TextContentParser {
|
|||||||
this.checkRestLine(width, guess);
|
this.checkRestLine(width, guess);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(this.renderable);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
lineHeights: this.lineHeights,
|
lineHeights: this.lineHeights,
|
||||||
data: this.renderable
|
data: this.renderable
|
||||||
|
Loading…
Reference in New Issue
Block a user