mirror of
https://github.com/unanmed/HumanBreak.git
synced 2026-11-01 15:44:30 +08:00
feat: 楼层选择组件 & fix: 滚动条交互错位
This commit is contained in:
1 parent
936c909451
commit
b7c7cdeca0
10 files changed
+1209
-798
No files matched your search
@@ -151,8 +151,23 @@ export type CustomContainerRenderFn = (
|
||||
transform: Transform
|
||||
) => void;
|
||||
|
||||
export type CustomContainerPropagateOrigin = <T extends ActionType>(
|
||||
type: T,
|
||||
progress: EventProgress,
|
||||
event: ActionEventMap[T]
|
||||
) => void;
|
||||
|
||||
export type CustomContainerPropagateFn = <T extends ActionType>(
|
||||
type: T,
|
||||
progress: EventProgress,
|
||||
event: ActionEventMap[T],
|
||||
container: ContainerCustom,
|
||||
origin: CustomContainerPropagateOrigin
|
||||
) => void;
|
||||
|
||||
export class ContainerCustom extends Container {
|
||||
private renderFn?: CustomContainerRenderFn;
|
||||
private propagateFn?: CustomContainerPropagateFn;
|
||||
|
||||
protected render(
|
||||
canvas: MotaOffscreenCanvas2D,
|
||||
@@ -165,6 +180,20 @@ export class ContainerCustom extends Container {
|
||||
}
|
||||
}
|
||||
|
||||
protected propagateEvent<T extends ActionType>(
|
||||
type: T,
|
||||
progress: EventProgress,
|
||||
event: ActionEventMap[T]
|
||||
): void {
|
||||
if (this.propagateFn) {
|
||||
this.propagateFn(type, progress, event, this, () => {
|
||||
super.propagateEvent(type, progress, event);
|
||||
});
|
||||
} else {
|
||||
super.propagateEvent(type, progress, event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置这个自定义容器的渲染函数
|
||||
* @param render 渲染函数
|
||||
@@ -173,6 +202,14 @@ export class ContainerCustom extends Container {
|
||||
this.renderFn = render;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置这个自定义容器的事件传递函数
|
||||
* @param propagate 事件传递函数
|
||||
*/
|
||||
setPropagateFn(propagate: CustomContainerPropagateFn) {
|
||||
this.propagateFn = propagate;
|
||||
}
|
||||
|
||||
protected handleProps(
|
||||
key: string,
|
||||
prevValue: any,
|
||||
@@ -184,6 +221,11 @@ export class ContainerCustom extends Container {
|
||||
this.setRenderFn(nextValue);
|
||||
return true;
|
||||
}
|
||||
case 'propagate': {
|
||||
if (!this.assertType(nextValue, 'function', key)) return false;
|
||||
this.setPropagateFn(nextValue);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.handleProps(key, prevValue, nextValue);
|
||||
}
|
||||
|
||||
@@ -73,11 +73,11 @@ export interface IActionEventBase {
|
||||
ctrlKey: boolean;
|
||||
/** 触发时是否按下了 Windows(Windows) / Command(Mac) 键 */
|
||||
metaKey: boolean;
|
||||
/** 这次操作的标识符,在按下、移动、抬起阶段中保持不变 */
|
||||
identifier: number;
|
||||
}
|
||||
|
||||
export interface IActionEvent extends IActionEventBase {
|
||||
/** 这次操作的标识符,在按下、移动、抬起阶段中保持不变 */
|
||||
identifier: number;
|
||||
/** 相对于触发元素左上角的横坐标 */
|
||||
offsetX: number;
|
||||
/** 相对于触发元素左上角的纵坐标 */
|
||||
|
||||
@@ -165,14 +165,19 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
||||
}
|
||||
this.checkMouseEnterLeave(
|
||||
ev,
|
||||
event,
|
||||
this.beforeHovered,
|
||||
this.hoveredElement
|
||||
);
|
||||
});
|
||||
canvas.addEventListener('mouseleave', ev => {
|
||||
ev.preventDefault();
|
||||
const id = this.getMouseIdentifier(
|
||||
ActionType.Leave,
|
||||
this.getMouseType(ev)
|
||||
);
|
||||
this.hoveredElement.forEach(v => {
|
||||
v.emit('leave', this.createMouseActionBase(ev, v));
|
||||
v.emit('leave', this.createMouseActionBase(ev, id, v));
|
||||
});
|
||||
this.hoveredElement.clear();
|
||||
this.beforeHovered.clear();
|
||||
@@ -210,6 +215,7 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
||||
this.captureEvent(ActionType.Move, v);
|
||||
this.checkTouchEnterLeave(
|
||||
ev,
|
||||
v,
|
||||
this.beforeHovered,
|
||||
this.hoveredElement
|
||||
);
|
||||
@@ -308,10 +314,12 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
||||
|
||||
private createMouseActionBase(
|
||||
event: MouseEvent,
|
||||
id: number,
|
||||
target: RenderItem = this,
|
||||
mouse: MouseType = this.getMouseType(event)
|
||||
): IActionEventBase {
|
||||
return {
|
||||
identifier: id,
|
||||
target: target,
|
||||
touch: false,
|
||||
type: mouse,
|
||||
@@ -325,9 +333,11 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
||||
|
||||
private createTouchActionBase(
|
||||
event: TouchEvent,
|
||||
id: number,
|
||||
target: RenderItem
|
||||
): IActionEventBase {
|
||||
return {
|
||||
identifier: id,
|
||||
target: target,
|
||||
touch: false,
|
||||
type: MouseType.Left,
|
||||
@@ -480,36 +490,50 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
||||
|
||||
private checkMouseEnterLeave(
|
||||
event: MouseEvent,
|
||||
ev: IActionEvent,
|
||||
before: Set<RenderItem>,
|
||||
now: Set<RenderItem>
|
||||
) {
|
||||
// 先 leave,再 enter
|
||||
before.forEach(v => {
|
||||
if (!now.has(v)) {
|
||||
v.emit('leave', this.createMouseActionBase(event, v));
|
||||
v.emit(
|
||||
'leave',
|
||||
this.createMouseActionBase(event, ev.identifier, v)
|
||||
);
|
||||
}
|
||||
});
|
||||
now.forEach(v => {
|
||||
if (!before.has(v)) {
|
||||
v.emit('enter', this.createMouseActionBase(event, v));
|
||||
v.emit(
|
||||
'enter',
|
||||
this.createMouseActionBase(event, ev.identifier, v)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private checkTouchEnterLeave(
|
||||
event: TouchEvent,
|
||||
ev: IActionEvent,
|
||||
before: Set<RenderItem>,
|
||||
now: Set<RenderItem>
|
||||
) {
|
||||
// 先 leave,再 enter
|
||||
before.forEach(v => {
|
||||
if (!now.has(v)) {
|
||||
v.emit('leave', this.createTouchActionBase(event, v));
|
||||
v.emit(
|
||||
'leave',
|
||||
this.createTouchActionBase(event, ev.identifier, v)
|
||||
);
|
||||
}
|
||||
});
|
||||
now.forEach(v => {
|
||||
if (!before.has(v)) {
|
||||
v.emit('enter', this.createTouchActionBase(event, v));
|
||||
v.emit(
|
||||
'enter',
|
||||
this.createTouchActionBase(event, ev.identifier, v)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user