From a42b2ffcf48ae890a47e05aab9518051bd7f725f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E4=BA=91=E9=A3=9E?= Date: Sun, 28 Nov 2021 13:05:08 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E9=A1=B5=E7=A0=81=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 15 ++++ src/assets/images/page-add.svg | 1 + src/assets/images/page-minus.svg | 1 + src/editor/core/draw/Draw.ts | 35 +++++++++ src/editor/core/listener/Listener.ts | 13 +++- src/editor/core/observer/GlobalObserver.ts | 60 +++++++++++++++ src/editor/dataset/enum/Editor.ts | 3 +- src/editor/interface/Listener.ts | 6 ++ src/main.ts | 13 ++++ src/style.css | 90 ++++++++++++++++++++++ 10 files changed, 235 insertions(+), 2 deletions(-) create mode 100644 src/assets/images/page-add.svg create mode 100644 src/assets/images/page-minus.svg create mode 100644 src/editor/core/observer/GlobalObserver.ts diff --git a/index.html b/index.html index d60a988..059867e 100644 --- a/index.html +++ b/index.html @@ -115,6 +115,21 @@
+ diff --git a/src/assets/images/page-add.svg b/src/assets/images/page-add.svg new file mode 100644 index 0000000..bcfa9a3 --- /dev/null +++ b/src/assets/images/page-add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/page-minus.svg b/src/assets/images/page-minus.svg new file mode 100644 index 0000000..f85bf77 --- /dev/null +++ b/src/assets/images/page-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/editor/core/draw/Draw.ts b/src/editor/core/draw/Draw.ts index 879a821..341ebfa 100644 --- a/src/editor/core/draw/Draw.ts +++ b/src/editor/core/draw/Draw.ts @@ -22,6 +22,7 @@ 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" export class Draw { @@ -52,6 +53,8 @@ export class Draw { private rowList: IRow[] private painterStyle: IElementStyle | null private searchMatchList: number[][] | null + private visiblePageNoList: number[] + private intersectionPageNo: number constructor( container: HTMLDivElement, @@ -82,6 +85,7 @@ export class Draw { this.imageParticle = new ImageParticle(this) this.textParticle = new TextParticle(this) this.pageNumber = new PageNumber(this) + new GlobalObserver(this) const canvasEvent = new CanvasEvent(this) this.cursor = new Cursor(this, canvasEvent) @@ -94,6 +98,8 @@ export class Draw { this.rowList = [] this.painterStyle = null this.searchMatchList = null + this.visiblePageNoList = [] + this.intersectionPageNo = 0 this.render({ isSetCursor: false }) } @@ -106,6 +112,28 @@ export class Draw { return this.pageContainer } + public getVisiblePageNoList(): number[] { + return this.visiblePageNoList + } + + public setVisiblePageNoList(payload: number[]) { + this.visiblePageNoList = payload + if (this.listener.visiblePageNoListChange) { + this.listener.visiblePageNoListChange(this.visiblePageNoList) + } + } + + public getIntersectionPageNo(): number { + return this.intersectionPageNo + } + + public setIntersectionPageNo(payload: number) { + this.intersectionPageNo = payload + if (this.listener.intersectionPageNoChange) { + this.listener.intersectionPageNoChange(this.intersectionPageNo) + } + } + public getPageNo(): number { return this.pageNo } @@ -467,6 +495,13 @@ export class Draw { self.render({ curIndex, isSubmitHistory: false }) }) } + + // 页面改变 + setTimeout(() => { + if (this.listener.pageSizeChange) { + this.listener.pageSizeChange(pageRowList.length) + } + }) } } \ No newline at end of file diff --git a/src/editor/core/listener/Listener.ts b/src/editor/core/listener/Listener.ts index f750060..a4bb989 100644 --- a/src/editor/core/listener/Listener.ts +++ b/src/editor/core/listener/Listener.ts @@ -1,11 +1,22 @@ -import { IRangeStyleChange } from "../../interface/Listener" +import { + IIntersectionPageNoChange, + IPageSizeChange, + IRangeStyleChange, + IVisiblePageNoListChange +} from "../../interface/Listener" export class Listener { public rangeStyleChange: IRangeStyleChange | null + public visiblePageNoListChange: IVisiblePageNoListChange | null + public intersectionPageNoChange: IIntersectionPageNoChange | null + public pageSizeChange: IPageSizeChange | null constructor() { this.rangeStyleChange = null + this.visiblePageNoListChange = null + this.intersectionPageNoChange = null + this.pageSizeChange = null } } \ No newline at end of file diff --git a/src/editor/core/observer/GlobalObserver.ts b/src/editor/core/observer/GlobalObserver.ts new file mode 100644 index 0000000..185b4eb --- /dev/null +++ b/src/editor/core/observer/GlobalObserver.ts @@ -0,0 +1,60 @@ +import { IEditorOption } from "../../interface/Editor" +import { debounce } from "../../utils" +import { Draw } from "../draw/Draw" + +export class GlobalObserver { + + private draw: Draw + private options: Required + private pageContainer: HTMLDivElement + private pageHeight: number + + constructor(draw: Draw) { + this.draw = draw + this.options = draw.getOptions() + this.pageContainer = draw.getPageContainer() + const { height, pageGap } = this.options + this.pageHeight = height + pageGap + // 监听滚轮 + setTimeout(() => { + if (!window.scrollY) { + this.observer() + } + }) + document.addEventListener('scroll', debounce(this.observer.bind(this), 150)) + } + + private observer() { + const rect = this.pageContainer.getBoundingClientRect() + const top = Math.abs(rect.top) + const bottom = top + window.innerHeight + const pageList = this.draw.getPageList() + // 计算显示页 + let visiblePageNoList: number[] = [] + let intersectionPageNo: number = 0 + let intersectionMaxHeight: number = 0 + for (let i = 0; i < pageList.length; i++) { + const curTop = i * this.pageHeight + const curBottom = (i + 1) * this.pageHeight + if (curTop > bottom) break + if (curBottom < top) continue + // 计算交叉高度 + let intersectionHeight = 0 + if (curTop < top && curBottom < bottom) { + intersectionHeight = curBottom - top + } else if (curTop > top && curBottom > bottom) { + intersectionHeight = bottom - curTop + } else { + intersectionHeight = rect.height + } + if (intersectionHeight > intersectionMaxHeight) { + intersectionMaxHeight = intersectionHeight + intersectionPageNo = i + } + visiblePageNoList.push(i) + } + this.draw.setIntersectionPageNo(intersectionPageNo) + this.draw.setVisiblePageNoList(visiblePageNoList) + } + +} \ No newline at end of file diff --git a/src/editor/dataset/enum/Editor.ts b/src/editor/dataset/enum/Editor.ts index 36a7d0e..8376db2 100644 --- a/src/editor/dataset/enum/Editor.ts +++ b/src/editor/dataset/enum/Editor.ts @@ -1,4 +1,5 @@ export enum EditorComponent { MENU = 'menu', - MAIN = 'main' + MAIN = 'main', + FOOTER = 'footer' } \ No newline at end of file diff --git a/src/editor/interface/Listener.ts b/src/editor/interface/Listener.ts index 2f5dc19..f0ca881 100644 --- a/src/editor/interface/Listener.ts +++ b/src/editor/interface/Listener.ts @@ -16,3 +16,9 @@ export interface IRangeStype { } export type IRangeStyleChange = (payload: IRangeStype) => void + +export type IVisiblePageNoListChange = (payload: number[]) => void + +export type IIntersectionPageNoChange = (payload: number) => void + +export type IPageSizeChange = (payload: number) => void diff --git a/src/main.ts b/src/main.ts index 099d1cc..ca5fbc9 100644 --- a/src/main.ts +++ b/src/main.ts @@ -282,4 +282,17 @@ window.onload = function () { payload.painter ? painterDom.classList.add('active') : painterDom.classList.remove('active') } + instance.listener.visiblePageNoListChange = function (payload) { + const text = payload.map(i => i + 1).join('、') + document.querySelector('.page-no-list')!.innerText = text + } + + instance.listener.pageSizeChange = function (payload) { + document.querySelector('.page-size')!.innerText = `${payload}` + } + + instance.listener.intersectionPageNoChange = function (payload) { + document.querySelector('.page-no')!.innerText = `${payload + 1}` + } + } \ No newline at end of file diff --git a/src/style.css b/src/style.css index ed24899..047d19a 100644 --- a/src/style.css +++ b/src/style.css @@ -1,3 +1,35 @@ +::-webkit-scrollbar { + height: 16px; + width: 16px; + overflow: visible +} + +::-webkit-scrollbar-button { + width: 0; + height: 0 +} + +::-webkit-scrollbar-corner { + background: transparent +} + +::-webkit-scrollbar-thumb { + background-color: #ddd; + background-clip: padding-box; + border: 4px solid #f2f4f7; + border-radius: 8px; + min-height: 24px +} + +::-webkit-scrollbar-thumb:hover { + background-color: #c9c9c9 +} + +::-webkit-scrollbar-track { + background: #f2f4f7; + background-clip: padding-box +} + * { margin: 0; padding: 0; @@ -312,4 +344,62 @@ ul { display: block; background-color: #ffffff; box-shadow: rgb(158 161 165 / 40%) 0px 2px 12px 0px; +} + +.footer { + width: 100%; + height: 30px; + display: flex; + align-items: center; + justify-content: space-between; + background: #f2f4f7; + z-index: 9; + overflow: hidden; + position: fixed; + bottom: 0; + left: 0; + font-size: 12px; + padding: 0 4px 0 20px; + box-sizing: border-box; +} + +.footer>div:first-child>span { + display: inline-block; + margin-right: 5px; + letter-spacing: 1px; +} + +.footer>div:last-child { + width: 120px; + display: flex; + align-items: center; + justify-content: space-between; +} + +.footer>div:last-child>div { + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; +} + +.footer>div:last-child>div:hover { + background: rgba(25, 55, 88, .04); +} + +.footer>div:last-child i { + width: 16px; + height: 16px; + display: inline-block; + cursor: pointer; +} + +.footer>div:last-child .page-minus { + background-image: url('./assets/images/page-minus.svg'); + +} + +.footer>div:last-child .page-add { + background-image: url('./assets/images/page-add.svg'); } \ No newline at end of file