feat: add mouse event listener #603
This commit is contained in:
@@ -241,3 +241,29 @@ const {
|
|||||||
zone: EditorZone
|
zone: EditorZone
|
||||||
}[] = await instance.command.getTitleValue(payload: IGetTitleValueOption)
|
}[] = 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
|
```javascript
|
||||||
instance.eventBus.on('zoneChange', (payload: EditorZone) => void)
|
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
|
zone: EditorZone
|
||||||
}[] = await instance.command.getTitleValue(payload: IGetTitleValueOption)
|
}[] = 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
|
```javascript
|
||||||
instance.eventBus.on('zoneChange', (payload: EditorZone) => void)
|
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 getControlList: CommandAdapt['getControlList']
|
||||||
public getContainer: CommandAdapt['getContainer']
|
public getContainer: CommandAdapt['getContainer']
|
||||||
public getTitleValue: CommandAdapt['getTitleValue']
|
public getTitleValue: CommandAdapt['getTitleValue']
|
||||||
|
public getPositionContextByEvent: CommandAdapt['getPositionContextByEvent']
|
||||||
|
|
||||||
constructor(adapt: CommandAdapt) {
|
constructor(adapt: CommandAdapt) {
|
||||||
// 全局命令
|
// 全局命令
|
||||||
@@ -232,6 +233,7 @@ export class Command {
|
|||||||
this.getGroupIds = adapt.getGroupIds.bind(adapt)
|
this.getGroupIds = adapt.getGroupIds.bind(adapt)
|
||||||
this.getContainer = adapt.getContainer.bind(adapt)
|
this.getContainer = adapt.getContainer.bind(adapt)
|
||||||
this.getTitleValue = adapt.getTitleValue.bind(adapt)
|
this.getTitleValue = adapt.getTitleValue.bind(adapt)
|
||||||
|
this.getPositionContextByEvent = adapt.getPositionContextByEvent.bind(adapt)
|
||||||
// 控件
|
// 控件
|
||||||
this.executeSetControlValue = adapt.setControlValue.bind(adapt)
|
this.executeSetControlValue = adapt.setControlValue.bind(adapt)
|
||||||
this.executeSetControlExtension = adapt.setControlExtension.bind(adapt)
|
this.executeSetControlExtension = adapt.setControlExtension.bind(adapt)
|
||||||
|
|||||||
@@ -55,10 +55,11 @@ import {
|
|||||||
} from '../../interface/Editor'
|
} from '../../interface/Editor'
|
||||||
import {
|
import {
|
||||||
IElement,
|
IElement,
|
||||||
|
IElementPosition,
|
||||||
IElementStyle,
|
IElementStyle,
|
||||||
IUpdateElementByIdOption
|
IUpdateElementByIdOption
|
||||||
} from '../../interface/Element'
|
} from '../../interface/Element'
|
||||||
import { IPasteOption } from '../../interface/Event'
|
import { IPasteOption, IPositionContextByEvent } from '../../interface/Event'
|
||||||
import { IMargin } from '../../interface/Margin'
|
import { IMargin } from '../../interface/Margin'
|
||||||
import { ILocationPosition } from '../../interface/Position'
|
import { ILocationPosition } from '../../interface/Position'
|
||||||
import { IRange, RangeContext, RangeRect } from '../../interface/Range'
|
import { IRange, RangeContext, RangeRect } from '../../interface/Range'
|
||||||
@@ -102,6 +103,7 @@ import { I18n } from '../i18n/I18n'
|
|||||||
import { Position } from '../position/Position'
|
import { Position } from '../position/Position'
|
||||||
import { RangeManager } from '../range/RangeManager'
|
import { RangeManager } from '../range/RangeManager'
|
||||||
import { WorkerManager } from '../worker/WorkerManager'
|
import { WorkerManager } from '../worker/WorkerManager'
|
||||||
|
import { Zone } from '../zone/Zone'
|
||||||
|
|
||||||
export class CommandAdapt {
|
export class CommandAdapt {
|
||||||
private draw: Draw
|
private draw: Draw
|
||||||
@@ -115,6 +117,7 @@ export class CommandAdapt {
|
|||||||
private workerManager: WorkerManager
|
private workerManager: WorkerManager
|
||||||
private searchManager: Search
|
private searchManager: Search
|
||||||
private i18n: I18n
|
private i18n: I18n
|
||||||
|
private zone: Zone
|
||||||
|
|
||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
this.draw = draw
|
this.draw = draw
|
||||||
@@ -128,6 +131,7 @@ export class CommandAdapt {
|
|||||||
this.workerManager = draw.getWorkerManager()
|
this.workerManager = draw.getWorkerManager()
|
||||||
this.searchManager = draw.getSearch()
|
this.searchManager = draw.getSearch()
|
||||||
this.i18n = draw.getI18n()
|
this.i18n = draw.getI18n()
|
||||||
|
this.zone = draw.getZone()
|
||||||
}
|
}
|
||||||
|
|
||||||
public mode(payload: EditorMode) {
|
public mode(payload: EditorMode) {
|
||||||
@@ -2637,6 +2641,65 @@ export class CommandAdapt {
|
|||||||
return result
|
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) {
|
public insertTitle(payload: IElement) {
|
||||||
const isReadonly = this.draw.isReadonly()
|
const isReadonly = this.draw.isReadonly()
|
||||||
if (isReadonly) return
|
if (isReadonly) return
|
||||||
|
|||||||
@@ -43,9 +43,10 @@ export class CursorAgent {
|
|||||||
this.canvasEvent.keydown(evt)
|
this.canvasEvent.keydown(evt)
|
||||||
}
|
}
|
||||||
|
|
||||||
private _input(evt: InputEvent) {
|
private _input(evt: Event) {
|
||||||
if (!evt.data) return
|
const data = (<InputEvent>evt).data
|
||||||
this.canvasEvent.input(evt.data)
|
if (!data) return
|
||||||
|
this.canvasEvent.input(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
private _paste(evt: ClipboardEvent) {
|
private _paste(evt: ClipboardEvent) {
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ import { Override } from '../override/Override'
|
|||||||
import { ImageDisplay } from '../../dataset/enum/Common'
|
import { ImageDisplay } from '../../dataset/enum/Common'
|
||||||
import { PUNCTUATION_REG } from '../../dataset/constant/Regular'
|
import { PUNCTUATION_REG } from '../../dataset/constant/Regular'
|
||||||
import { LineBreakParticle } from './particle/LineBreakParticle'
|
import { LineBreakParticle } from './particle/LineBreakParticle'
|
||||||
|
import { MouseObserver } from '../observer/MouseObserver'
|
||||||
|
|
||||||
export class Draw {
|
export class Draw {
|
||||||
private container: HTMLDivElement
|
private container: HTMLDivElement
|
||||||
@@ -231,6 +232,7 @@ export class Draw {
|
|||||||
this.scrollObserver = new ScrollObserver(this)
|
this.scrollObserver = new ScrollObserver(this)
|
||||||
this.selectionObserver = new SelectionObserver(this)
|
this.selectionObserver = new SelectionObserver(this)
|
||||||
this.imageObserver = new ImageObserver()
|
this.imageObserver = new ImageObserver()
|
||||||
|
new MouseObserver(this)
|
||||||
|
|
||||||
this.canvasEvent = new CanvasEvent(this)
|
this.canvasEvent = new CanvasEvent(this)
|
||||||
this.cursor = new Cursor(this, this.canvasEvent)
|
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,
|
x,
|
||||||
y,
|
y,
|
||||||
td,
|
td,
|
||||||
|
pageNo: curPageNo,
|
||||||
tablePosition: positionList[j],
|
tablePosition: positionList[j],
|
||||||
isTable: true,
|
isTable: true,
|
||||||
elementList: td.value,
|
elementList: td.value,
|
||||||
@@ -460,6 +461,7 @@ export class Position {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
isDirectHit: true,
|
||||||
hitLineStartIndex,
|
hitLineStartIndex,
|
||||||
index: curPositionIndex,
|
index: curPositionIndex,
|
||||||
isControl: !!element.controlId
|
isControl: !!element.controlId
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
import { IElement } from './Element'
|
||||||
|
import { RangeRect } from './Range'
|
||||||
|
|
||||||
export interface IPasteOption {
|
export interface IPasteOption {
|
||||||
isPlainText: boolean
|
isPlainText: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IPositionContextByEvent {
|
||||||
|
pageNo: number
|
||||||
|
element: IElement | null
|
||||||
|
rangeRect: RangeRect | null
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import {
|
|||||||
IContentChange,
|
IContentChange,
|
||||||
IControlChange,
|
IControlChange,
|
||||||
IIntersectionPageNoChange,
|
IIntersectionPageNoChange,
|
||||||
|
IMouseEventChange,
|
||||||
IPageModeChange,
|
IPageModeChange,
|
||||||
IPageScaleChange,
|
IPageScaleChange,
|
||||||
IPageSizeChange,
|
IPageSizeChange,
|
||||||
@@ -22,4 +23,7 @@ export interface EventBusMap {
|
|||||||
controlChange: IControlChange
|
controlChange: IControlChange
|
||||||
pageModeChange: IPageModeChange
|
pageModeChange: IPageModeChange
|
||||||
zoneChange: IZoneChange
|
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 IPageModeChange = (payload: PageMode) => void
|
||||||
|
|
||||||
export type IZoneChange = (payload: EditorZone) => 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'
|
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
|
let timer: number
|
||||||
return function (this: any, ...args: any[]) {
|
return function (this: unknown, ...args: T) {
|
||||||
if (timer) {
|
if (timer) {
|
||||||
window.clearTimeout(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 lastExecTime = 0
|
||||||
let timer: number
|
let timer: number
|
||||||
return function (this: any, ...args: any[]) {
|
return function (this: unknown, ...args: T) {
|
||||||
const currentTime = Date.now()
|
const currentTime = Date.now()
|
||||||
if (currentTime - lastExecTime >= delay) {
|
if (currentTime - lastExecTime >= delay) {
|
||||||
window.clearTimeout(timer)
|
window.clearTimeout(timer)
|
||||||
|
|||||||
+5
-2
@@ -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
|
let timer: number
|
||||||
return function (this: any, ...args: any[]) {
|
return function (this: unknown, ...args: T) {
|
||||||
if (timer) {
|
if (timer) {
|
||||||
window.clearTimeout(timer)
|
window.clearTimeout(timer)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user