refactor(right-key): move interaction logic to component and trigger on mouseup
This commit is contained in:
@@ -13,8 +13,13 @@ export class BimRightKey implements IBimComponent {
|
|||||||
private content: IRightKeyContent | null = null;
|
private content: IRightKeyContent | null = null;
|
||||||
private isVisible: boolean = false;
|
private isVisible: boolean = false;
|
||||||
private onCloseCallback?: () => void;
|
private onCloseCallback?: () => void;
|
||||||
|
private options?: RightKeyOptions;
|
||||||
|
|
||||||
|
private mouseDownTime: number = 0;
|
||||||
|
private readonly CLICK_THRESHOLD: number = 200; // ms
|
||||||
|
|
||||||
constructor(options?: RightKeyOptions) {
|
constructor(options?: RightKeyOptions) {
|
||||||
|
this.options = options;
|
||||||
this.element = document.createElement('div');
|
this.element = document.createElement('div');
|
||||||
this.element.className = `bim-right-key ${options?.className || ''}`;
|
this.element.className = `bim-right-key ${options?.className || ''}`;
|
||||||
|
|
||||||
@@ -36,6 +41,13 @@ export class BimRightKey implements IBimComponent {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 绑定容器交互事件
|
||||||
|
if (this.options?.container) {
|
||||||
|
this.options.container.addEventListener('mousedown', this.handleContainerMouseDown);
|
||||||
|
this.options.container.addEventListener('mouseup', this.handleContainerMouseUp);
|
||||||
|
this.options.container.addEventListener('contextmenu', this.handleContainerContextMenu);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setTheme(_theme: ThemeConfig): void {
|
public setTheme(_theme: ThemeConfig): void {
|
||||||
@@ -51,10 +63,46 @@ export class BimRightKey implements IBimComponent {
|
|||||||
|
|
||||||
public destroy(): void {
|
public destroy(): void {
|
||||||
document.removeEventListener('mousedown', this.handleGlobalClick);
|
document.removeEventListener('mousedown', this.handleGlobalClick);
|
||||||
|
|
||||||
|
if (this.options?.container) {
|
||||||
|
this.options.container.removeEventListener('mousedown', this.handleContainerMouseDown);
|
||||||
|
this.options.container.removeEventListener('mouseup', this.handleContainerMouseUp);
|
||||||
|
this.options.container.removeEventListener('contextmenu', this.handleContainerContextMenu);
|
||||||
|
}
|
||||||
|
|
||||||
this.unmountContent();
|
this.unmountContent();
|
||||||
this.element.remove();
|
this.element.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private handleContainerMouseDown = (e: MouseEvent): void => {
|
||||||
|
// 记录右键按下时间 (button 2 是右键)
|
||||||
|
if (e.button === 2) {
|
||||||
|
this.mouseDownTime = Date.now();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private handleContainerMouseUp = (e: MouseEvent): void => {
|
||||||
|
// 只处理右键 (button 2)
|
||||||
|
if (e.button !== 2) return;
|
||||||
|
|
||||||
|
// 检查点击时长,如果是长按或拖拽(时间过长),则不触发回调
|
||||||
|
const pressDuration = Date.now() - this.mouseDownTime;
|
||||||
|
if (pressDuration > this.CLICK_THRESHOLD) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 触发有效右键回调
|
||||||
|
if (this.options?.onContext) {
|
||||||
|
this.options.onContext(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private handleContainerContextMenu = (e: MouseEvent): void => {
|
||||||
|
// 阻止浏览器默认的右键菜单
|
||||||
|
// 真正的菜单触发逻辑已移至 mouseup,这里只负责拦截默认行为
|
||||||
|
e.preventDefault();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置关闭时的回调函数
|
* 设置关闭时的回调函数
|
||||||
* 通常用于通知 Manager 状态变更
|
* 通常用于通知 Manager 状态变更
|
||||||
@@ -80,7 +128,7 @@ export class BimRightKey implements IBimComponent {
|
|||||||
*/
|
*/
|
||||||
public unmountContent(): void {
|
public unmountContent(): void {
|
||||||
if (this.content) {
|
if (this.content) {
|
||||||
this.content.destroy(); // 重要:调用组件销毁方法清理资源
|
this.content.destroy(); // 重要:调用组件销毁方法清理<EFBFBD><EFBFBD><EFBFBD>源
|
||||||
this.element.innerHTML = '';
|
this.element.innerHTML = '';
|
||||||
this.content = null;
|
this.content = null;
|
||||||
}
|
}
|
||||||
@@ -100,7 +148,7 @@ export class BimRightKey implements IBimComponent {
|
|||||||
this.element.style.left = `${x}px`;
|
this.element.style.left = `${x}px`;
|
||||||
this.element.style.top = `${y}px`;
|
this.element.style.top = `${y}px`;
|
||||||
|
|
||||||
// 2. 获取容器<EFBFBD><EFBFBD><EFBFBD>寸和视口尺寸
|
// 2. 获取容器尺寸和视口尺寸
|
||||||
const rect = this.element.getBoundingClientRect();
|
const rect = this.element.getBoundingClientRect();
|
||||||
const viewportWidth = window.innerWidth;
|
const viewportWidth = window.innerWidth;
|
||||||
const viewportHeight = window.innerHeight;
|
const viewportHeight = window.innerHeight;
|
||||||
|
|||||||
@@ -15,4 +15,8 @@ export interface RightKeyOptions {
|
|||||||
className?: string;
|
className?: string;
|
||||||
/** 层级 (z-index) */
|
/** 层级 (z-index) */
|
||||||
zIndex?: number;
|
zIndex?: number;
|
||||||
|
/** 监听事件的容器 */
|
||||||
|
container?: HTMLElement;
|
||||||
|
/** 有效右键点击时的回调 */
|
||||||
|
onContext?: (e: MouseEvent) => void;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export class RightKeyManager extends BimComponent {
|
|||||||
private rightKeyPanel: BimRightKey;
|
private rightKeyPanel: BimRightKey;
|
||||||
|
|
||||||
// 存储注册的上下文处理器
|
// 存储注册的上下文处理器
|
||||||
// 每个处理<EFBFBD><EFBFBD>接收鼠标事件,返回一组菜单项(如果没有对应菜单则返回 null)
|
// 每个处理器接收鼠标事件,返回一组菜单项(如果没有对应菜单则返回 null)
|
||||||
private contextHandlers: Array<(e: MouseEvent) => MenuItemConfig[] | null> = [];
|
private contextHandlers: Array<(e: MouseEvent) => MenuItemConfig[] | null> = [];
|
||||||
|
|
||||||
constructor(engine: BimEngine, container: HTMLElement) {
|
constructor(engine: BimEngine, container: HTMLElement) {
|
||||||
@@ -24,18 +24,16 @@ export class RightKeyManager extends BimComponent {
|
|||||||
this.container = container;
|
this.container = container;
|
||||||
|
|
||||||
// 初始化右键容器,设置极高的层级以覆盖所有 UI
|
// 初始化右键容器,设置极高的层级以覆盖所有 UI
|
||||||
this.rightKeyPanel = new BimRightKey({ zIndex: 9000 });
|
// 将事件监听和触发逻辑下放给 BimRightKey 组件
|
||||||
|
this.rightKeyPanel = new BimRightKey({
|
||||||
|
zIndex: 9000,
|
||||||
|
container: this.container,
|
||||||
|
onContext: this.handleContextMenu
|
||||||
|
});
|
||||||
this.rightKeyPanel.init();
|
this.rightKeyPanel.init();
|
||||||
|
|
||||||
this.initEventListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
private initEventListeners(): void {
|
|
||||||
this.container.addEventListener('contextmenu', this.handleContextMenu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public destroy(): void {
|
public destroy(): void {
|
||||||
this.container.removeEventListener('contextmenu', this.handleContextMenu);
|
|
||||||
this.rightKeyPanel.destroy();
|
this.rightKeyPanel.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,11 +76,9 @@ export class RightKeyManager extends BimComponent {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理右键点击事件
|
* 处理右键点击事件
|
||||||
|
* 由 BimRightKey 组件在检测到有效右键点击时调用
|
||||||
*/
|
*/
|
||||||
private handleContextMenu = (e: MouseEvent): void => {
|
private handleContextMenu = (e: MouseEvent): void => {
|
||||||
// 阻止浏览器默认的右键菜单
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
// 1. 确定上下文项
|
// 1. 确定上下文项
|
||||||
// 遍历所有注册的处理器,找到第一个返回非空结果的处理器
|
// 遍历所有注册的处理器,找到第一个返回非空结果的处理器
|
||||||
// 这种责任链模式允许插件优先处理特定对象的右键
|
// 这种责任链模式允许插件优先处理特定对象的右键
|
||||||
|
|||||||
Reference in New Issue
Block a user