From ad7688854b4a75897acbacef47479026070bf049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E4=BA=91=E9=A3=9E?= Date: Thu, 24 Mar 2022 11:16:39 +0800 Subject: [PATCH] feat:add scrollbar scroll automatically at the boundary --- src/editor/core/draw/Draw.ts | 6 +- .../{GlobalObserver.ts => ScrollObserver.ts} | 8 +- src/editor/core/observer/SelectionObserver.ts | 85 +++++++++++++++++++ src/editor/dataset/enum/Observer.ts | 6 ++ 4 files changed, 99 insertions(+), 6 deletions(-) rename src/editor/core/observer/{GlobalObserver.ts => ScrollObserver.ts} (91%) create mode 100644 src/editor/core/observer/SelectionObserver.ts create mode 100644 src/editor/dataset/enum/Observer.ts diff --git a/src/editor/core/draw/Draw.ts b/src/editor/core/draw/Draw.ts index 9d20ecd..736537a 100644 --- a/src/editor/core/draw/Draw.ts +++ b/src/editor/core/draw/Draw.ts @@ -22,7 +22,8 @@ import { ElementType } from '../../dataset/enum/Element' import { ImageParticle } from './particle/ImageParticle' import { TextParticle } from './particle/TextParticle' import { PageNumber } from './frame/PageNumber' -import { GlobalObserver } from '../observer/GlobalObserver' +import { ScrollObserver } from '../observer/ScrollObserver' +import { SelectionObserver } from '../observer/SelectionObserver' import { TableParticle } from './particle/table/TableParticle' import { TableTool } from './particle/table/TableTool' import { HyperlinkParticle } from './particle/HyperlinkParticle' @@ -116,7 +117,8 @@ export class Draw { this.superscriptParticle = new SuperscriptParticle() this.subscriptParticle = new SubscriptParticle() - new GlobalObserver(this) + new ScrollObserver(this) + new SelectionObserver() this.canvasEvent = new CanvasEvent(this) this.cursor = new Cursor(this, this.canvasEvent) diff --git a/src/editor/core/observer/GlobalObserver.ts b/src/editor/core/observer/ScrollObserver.ts similarity index 91% rename from src/editor/core/observer/GlobalObserver.ts rename to src/editor/core/observer/ScrollObserver.ts index f3a550b..e65e87f 100644 --- a/src/editor/core/observer/GlobalObserver.ts +++ b/src/editor/core/observer/ScrollObserver.ts @@ -2,7 +2,7 @@ import { IEditorOption } from '../../interface/Editor' import { debounce } from '../../utils' import { Draw } from '../draw/Draw' -export class GlobalObserver { +export class ScrollObserver { private draw: Draw private options: Required @@ -18,13 +18,13 @@ export class GlobalObserver { // 监听滚轮 setTimeout(() => { if (!window.scrollY) { - this.observer() + this._observer() } }) - document.addEventListener('scroll', debounce(this.observer.bind(this), 150)) + document.addEventListener('scroll', debounce(this._observer.bind(this), 150)) } - private observer() { + private _observer() { const rect = this.pageContainer.getBoundingClientRect() const top = Math.abs(rect.top) const bottom = top + window.innerHeight diff --git a/src/editor/core/observer/SelectionObserver.ts b/src/editor/core/observer/SelectionObserver.ts new file mode 100644 index 0000000..fa83239 --- /dev/null +++ b/src/editor/core/observer/SelectionObserver.ts @@ -0,0 +1,85 @@ +import { MoveDirection } from '../../dataset/enum/Observer' + +export class SelectionObserver { + + private threshold: number + private requestAnimationFrameId: number + private tippingPoints: [top: number, down: number, left: number, right: number] + + private isMousedown: boolean + private isMoving: boolean + private clientWidth: number + private clientHeight: number + + constructor() { + this.threshold = 10 + this.tippingPoints = [70, 40, 10, 20] + this.requestAnimationFrameId = -1 + + this.isMousedown = false + this.isMoving = false + this.clientWidth = 0 + this.clientHeight = 0 + + document.addEventListener('mousedown', this._mousedown.bind(this)) + document.addEventListener('mousemove', this._mousemove.bind(this)) + document.addEventListener('mouseup', this._mouseup.bind(this)) + } + + private _mousedown() { + this.isMousedown = true + } + + private _mouseup() { + this.isMousedown = false + this._stopMove() + } + + private _mousemove(evt: MouseEvent) { + if (!this.isMousedown) return + const { x, y } = evt + if (y < this.tippingPoints[0]) { + this._startMove(MoveDirection.UP) + } else if (this.clientHeight - y <= this.tippingPoints[1]) { + this._startMove(MoveDirection.DOWN) + } else if (x < this.tippingPoints[2]) { + this._startMove(MoveDirection.LEFT) + } else if (this.clientWidth - x < this.tippingPoints[3]) { + this._startMove(MoveDirection.RIGHT) + } else { + this._stopMove() + } + } + + private _move(direction: MoveDirection) { + const x = window.screenX + const y = window.screenY + if (direction === MoveDirection.DOWN) { + window.scrollBy(x, y + this.threshold) + } else if (direction === MoveDirection.UP) { + window.scrollBy(x, y - this.threshold) + } else if (direction === MoveDirection.LEFT) { + window.scrollBy(x - this.threshold, y) + } else { + window.scrollBy(x + this.threshold, y) + } + this.requestAnimationFrameId = window.requestAnimationFrame(this._move.bind(this, direction)) + } + + private _startMove(direction: MoveDirection) { + if (this.isMoving) return + this.clientWidth = document.documentElement.clientWidth + this.clientHeight = document.documentElement.clientHeight + this.isMoving = true + this.requestAnimationFrameId = window.requestAnimationFrame(this._move.bind(this, direction)) + } + + private _stopMove() { + if (!this.isMoving) return + if (~this.requestAnimationFrameId) { + window.cancelAnimationFrame(this.requestAnimationFrameId) + } + this.isMoving = false + } + +} \ No newline at end of file diff --git a/src/editor/dataset/enum/Observer.ts b/src/editor/dataset/enum/Observer.ts new file mode 100644 index 0000000..2d44c48 --- /dev/null +++ b/src/editor/dataset/enum/Observer.ts @@ -0,0 +1,6 @@ +export enum MoveDirection { + UP = 'top', + DOWN = 'down', + LEFT = 'left', + RIGHT = 'right' +} \ No newline at end of file