feat: add mouse event listener #603

pr675
Hufe 2 years ago committed by GitHub
parent 959a062f83
commit a2978bd1f5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -241,3 +241,29 @@ const {
zone: EditorZone
}[] = await instance.command.getTitleValue(payload: IGetTitleValueOption)
```
## getPositionContextByEvent
Feature: Get position context by mouse event
Usage:
```javascript
const {
pageNo: number
element: IElement | null
rangeRect: RangeRect | null
}[] = await instance.command.getPositionContextByEvent(evt: MouseEvent)
```
demo:
```javascript
instance.eventBus.on(
'mousemove',
debounce(evt => {
const positionContext = instance.command.getPositionContextByEvent(evt)
console.log(positionContext)
}, 200)
)``
```

@ -119,3 +119,33 @@ Usage:
```javascript
instance.eventBus.on('zoneChange', (payload: EditorZone) => void)
```
## mousemove
Feature: Editor mousemove event
Usage:
```javascript
instance.eventBus.on('mousemove', (evt: MouseEvent) => void)
```
## mouseenter
Feature: Editor mouseenter event
Usage:
```javascript
instance.eventBus.on('mouseenter', (evt: MouseEvent) => void)
```
## mouseleave
Feature: Editor mouseleave event
Usage:
```javascript
instance.eventBus.on('mouseleave', (evt: MouseEvent) => void)
```

@ -242,3 +242,29 @@ const {
zone: EditorZone
}[] = await instance.command.getTitleValue(payload: IGetTitleValueOption)
```
## getPositionContextByEvent
功能:获取位置上下文信息通过鼠标事件
用法:
```javascript
const {
pageNo: number
element: IElement | null
rangeRect: RangeRect | null
}[] = await instance.command.getPositionContextByEvent(evt: MouseEvent)
```
示例:
```javascript
instance.eventBus.on(
'mousemove',
debounce(evt => {
const positionContext = instance.command.getPositionContextByEvent(evt)
console.log(positionContext)
}, 200)
)``
```

@ -119,3 +119,33 @@ instance.eventBus.on('saved', (payload: IEditorResult) => void)
```javascript
instance.eventBus.on('zoneChange', (payload: EditorZone) => void)
```
## mousemove
功能:编辑器 mousemove 事件监听
用法:
```javascript
instance.eventBus.on('mousemove', (evt: MouseEvent) => void)
```
## mouseenter
功能:编辑器 mouseenter 事件监听
用法:
```javascript
instance.eventBus.on('mouseenter', (evt: MouseEvent) => void)
```
## mouseleave
功能:编辑器 mouseleave 事件监听
用法:
```javascript
instance.eventBus.on('mouseleave', (evt: MouseEvent) => void)
```

@ -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)

@ -1,6 +1,9 @@
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)
}

Loading…
Cancel
Save