feat: add mouse event listener #603
This commit is contained in:
@@ -115,6 +115,7 @@ export class Command {
|
||||
public getControlList: CommandAdapt['getControlList']
|
||||
public getContainer: CommandAdapt['getContainer']
|
||||
public getTitleValue: CommandAdapt['getTitleValue']
|
||||
public getPositionContextByEvent: CommandAdapt['getPositionContextByEvent']
|
||||
|
||||
constructor(adapt: CommandAdapt) {
|
||||
// 全局命令
|
||||
@@ -232,6 +233,7 @@ export class Command {
|
||||
this.getGroupIds = adapt.getGroupIds.bind(adapt)
|
||||
this.getContainer = adapt.getContainer.bind(adapt)
|
||||
this.getTitleValue = adapt.getTitleValue.bind(adapt)
|
||||
this.getPositionContextByEvent = adapt.getPositionContextByEvent.bind(adapt)
|
||||
// 控件
|
||||
this.executeSetControlValue = adapt.setControlValue.bind(adapt)
|
||||
this.executeSetControlExtension = adapt.setControlExtension.bind(adapt)
|
||||
|
||||
@@ -55,10 +55,11 @@ import {
|
||||
} from '../../interface/Editor'
|
||||
import {
|
||||
IElement,
|
||||
IElementPosition,
|
||||
IElementStyle,
|
||||
IUpdateElementByIdOption
|
||||
} from '../../interface/Element'
|
||||
import { IPasteOption } from '../../interface/Event'
|
||||
import { IPasteOption, IPositionContextByEvent } from '../../interface/Event'
|
||||
import { IMargin } from '../../interface/Margin'
|
||||
import { ILocationPosition } from '../../interface/Position'
|
||||
import { IRange, RangeContext, RangeRect } from '../../interface/Range'
|
||||
@@ -102,6 +103,7 @@ import { I18n } from '../i18n/I18n'
|
||||
import { Position } from '../position/Position'
|
||||
import { RangeManager } from '../range/RangeManager'
|
||||
import { WorkerManager } from '../worker/WorkerManager'
|
||||
import { Zone } from '../zone/Zone'
|
||||
|
||||
export class CommandAdapt {
|
||||
private draw: Draw
|
||||
@@ -115,6 +117,7 @@ export class CommandAdapt {
|
||||
private workerManager: WorkerManager
|
||||
private searchManager: Search
|
||||
private i18n: I18n
|
||||
private zone: Zone
|
||||
|
||||
constructor(draw: Draw) {
|
||||
this.draw = draw
|
||||
@@ -128,6 +131,7 @@ export class CommandAdapt {
|
||||
this.workerManager = draw.getWorkerManager()
|
||||
this.searchManager = draw.getSearch()
|
||||
this.i18n = draw.getI18n()
|
||||
this.zone = draw.getZone()
|
||||
}
|
||||
|
||||
public mode(payload: EditorMode) {
|
||||
@@ -2637,6 +2641,65 @@ export class CommandAdapt {
|
||||
return result
|
||||
}
|
||||
|
||||
public getPositionContextByEvent(
|
||||
evt: MouseEvent
|
||||
): IPositionContextByEvent | null {
|
||||
const pageIndex = (<HTMLElement>evt.target)?.dataset.index
|
||||
if (!pageIndex) return null
|
||||
const pageNo = Number(pageIndex)
|
||||
const positionContext = this.position.getPositionByXY({
|
||||
x: evt.offsetX,
|
||||
y: evt.offsetY,
|
||||
pageNo
|
||||
})
|
||||
const {
|
||||
isDirectHit,
|
||||
isTable,
|
||||
index,
|
||||
trIndex,
|
||||
tdIndex,
|
||||
tdValueIndex,
|
||||
zone
|
||||
} = positionContext
|
||||
// 非直接命中或选区不一致时返回空值
|
||||
if (!isDirectHit || (zone && zone !== this.zone.getZone())) return null
|
||||
// 命中元素信息
|
||||
let element: IElement | null = null
|
||||
const elementList = this.draw.getOriginalElementList()
|
||||
let position: IElementPosition | null = null
|
||||
const positionList = this.position.getOriginalPositionList()
|
||||
if (isTable) {
|
||||
const td = elementList[index!].trList?.[trIndex!].tdList[tdIndex!]
|
||||
element = td?.value[tdValueIndex!] || null
|
||||
position = td?.positionList?.[tdValueIndex!] || null
|
||||
} else {
|
||||
element = elementList[index] || null
|
||||
position = positionList[index] || null
|
||||
}
|
||||
// 元素包围信息
|
||||
let rangeRect: RangeRect | null = null
|
||||
if (position) {
|
||||
const {
|
||||
pageNo,
|
||||
coordinate: { leftTop, rightTop },
|
||||
lineHeight
|
||||
} = position
|
||||
const height = this.draw.getOriginalHeight()
|
||||
const pageGap = this.draw.getOriginalPageGap()
|
||||
rangeRect = {
|
||||
x: leftTop[0],
|
||||
y: leftTop[1] + pageNo * (height + pageGap),
|
||||
width: rightTop[0] - leftTop[0],
|
||||
height: lineHeight
|
||||
}
|
||||
}
|
||||
return {
|
||||
pageNo,
|
||||
element,
|
||||
rangeRect
|
||||
}
|
||||
}
|
||||
|
||||
public insertTitle(payload: IElement) {
|
||||
const isReadonly = this.draw.isReadonly()
|
||||
if (isReadonly) return
|
||||
|
||||
@@ -43,9 +43,10 @@ export class CursorAgent {
|
||||
this.canvasEvent.keydown(evt)
|
||||
}
|
||||
|
||||
private _input(evt: InputEvent) {
|
||||
if (!evt.data) return
|
||||
this.canvasEvent.input(evt.data)
|
||||
private _input(evt: Event) {
|
||||
const data = (<InputEvent>evt).data
|
||||
if (!data) return
|
||||
this.canvasEvent.input(data)
|
||||
}
|
||||
|
||||
private _paste(evt: ClipboardEvent) {
|
||||
|
||||
@@ -99,6 +99,7 @@ import { Override } from '../override/Override'
|
||||
import { ImageDisplay } from '../../dataset/enum/Common'
|
||||
import { PUNCTUATION_REG } from '../../dataset/constant/Regular'
|
||||
import { LineBreakParticle } from './particle/LineBreakParticle'
|
||||
import { MouseObserver } from '../observer/MouseObserver'
|
||||
|
||||
export class Draw {
|
||||
private container: HTMLDivElement
|
||||
@@ -231,6 +232,7 @@ export class Draw {
|
||||
this.scrollObserver = new ScrollObserver(this)
|
||||
this.selectionObserver = new SelectionObserver(this)
|
||||
this.imageObserver = new ImageObserver()
|
||||
new MouseObserver(this)
|
||||
|
||||
this.canvasEvent = new CanvasEvent(this)
|
||||
this.cursor = new Cursor(this, this.canvasEvent)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { EventBusMap } from '../../interface/EventBus'
|
||||
import { Draw } from '../draw/Draw'
|
||||
import { EventBus } from '../event/eventbus/EventBus'
|
||||
|
||||
export class MouseObserver {
|
||||
private draw: Draw
|
||||
private eventBus: EventBus<EventBusMap>
|
||||
private pageContainer: HTMLDivElement
|
||||
constructor(draw: Draw) {
|
||||
this.draw = draw
|
||||
this.eventBus = this.draw.getEventBus()
|
||||
this.pageContainer = this.draw.getPageContainer()
|
||||
this.pageContainer.addEventListener('mousemove', this._mousemove.bind(this))
|
||||
this.pageContainer.addEventListener(
|
||||
'mouseenter',
|
||||
this._mouseenter.bind(this)
|
||||
)
|
||||
this.pageContainer.addEventListener(
|
||||
'mouseleave',
|
||||
this._mouseleave.bind(this)
|
||||
)
|
||||
}
|
||||
|
||||
private _mousemove(evt: MouseEvent) {
|
||||
if (!this.eventBus.isSubscribe('mousemove')) return
|
||||
this.eventBus.emit('mousemove', evt)
|
||||
}
|
||||
|
||||
private _mouseenter(evt: MouseEvent) {
|
||||
if (!this.eventBus.isSubscribe('mouseenter')) return
|
||||
this.eventBus.emit('mouseenter', evt)
|
||||
}
|
||||
|
||||
private _mouseleave(evt: MouseEvent) {
|
||||
if (!this.eventBus.isSubscribe('mouseleave')) return
|
||||
this.eventBus.emit('mouseleave', evt)
|
||||
}
|
||||
}
|
||||
@@ -383,6 +383,7 @@ export class Position {
|
||||
x,
|
||||
y,
|
||||
td,
|
||||
pageNo: curPageNo,
|
||||
tablePosition: positionList[j],
|
||||
isTable: true,
|
||||
elementList: td.value,
|
||||
@@ -460,6 +461,7 @@ export class Position {
|
||||
}
|
||||
}
|
||||
return {
|
||||
isDirectHit: true,
|
||||
hitLineStartIndex,
|
||||
index: curPositionIndex,
|
||||
isControl: !!element.controlId
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
import { IElement } from './Element'
|
||||
import { RangeRect } from './Range'
|
||||
|
||||
export interface IPasteOption {
|
||||
isPlainText: boolean
|
||||
}
|
||||
|
||||
export interface IPositionContextByEvent {
|
||||
pageNo: number
|
||||
element: IElement | null
|
||||
rangeRect: RangeRect | null
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
IContentChange,
|
||||
IControlChange,
|
||||
IIntersectionPageNoChange,
|
||||
IMouseEventChange,
|
||||
IPageModeChange,
|
||||
IPageScaleChange,
|
||||
IPageSizeChange,
|
||||
@@ -22,4 +23,7 @@ export interface EventBusMap {
|
||||
controlChange: IControlChange
|
||||
pageModeChange: IPageModeChange
|
||||
zoneChange: IZoneChange
|
||||
mousemove: IMouseEventChange
|
||||
mouseleave: IMouseEventChange
|
||||
mouseenter: IMouseEventChange
|
||||
}
|
||||
|
||||
@@ -54,3 +54,5 @@ export type IControlChange = (payload: IControl | null) => void
|
||||
export type IPageModeChange = (payload: PageMode) => void
|
||||
|
||||
export type IZoneChange = (payload: EditorZone) => void
|
||||
|
||||
export type IMouseEventChange = (evt: MouseEvent) => void
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { UNICODE_SYMBOL_REG } from '../dataset/constant/Regular'
|
||||
|
||||
export function debounce(func: Function, delay: number) {
|
||||
export function debounce<T extends unknown[]>(
|
||||
func: (...arg: T) => unknown,
|
||||
delay: number
|
||||
) {
|
||||
let timer: number
|
||||
return function (this: any, ...args: any[]) {
|
||||
return function (this: unknown, ...args: T) {
|
||||
if (timer) {
|
||||
window.clearTimeout(timer)
|
||||
}
|
||||
@@ -12,10 +15,13 @@ export function debounce(func: Function, delay: number) {
|
||||
}
|
||||
}
|
||||
|
||||
export function throttle(func: Function, delay: number) {
|
||||
export function throttle<T extends unknown[]>(
|
||||
func: (...arg: T) => unknown,
|
||||
delay: number
|
||||
) {
|
||||
let lastExecTime = 0
|
||||
let timer: number
|
||||
return function (this: any, ...args: any[]) {
|
||||
return function (this: unknown, ...args: T) {
|
||||
const currentTime = Date.now()
|
||||
if (currentTime - lastExecTime >= delay) {
|
||||
window.clearTimeout(timer)
|
||||
|
||||
Reference in New Issue
Block a user