feat:页码计算
This commit is contained in:
+15
@@ -115,6 +115,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="editor" editor-component="main"></div>
|
<div class="editor" editor-component="main"></div>
|
||||||
|
<div class="footer" editor-component="footer">
|
||||||
|
<div>
|
||||||
|
<span>可见页码:<span class="page-no-list">1</span></span>
|
||||||
|
<span>页面:<span class="page-no">1</span>/<span class="page-size">1</span></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<i class="page-minus"></i>
|
||||||
|
</div>
|
||||||
|
<span>100%</span>
|
||||||
|
<div>
|
||||||
|
<i class="page-add"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M7 7V3h2v4h4v2H9v4H7V9H3V7h4z" fill="#636363" fill-rule="evenodd"/></svg>
|
||||||
|
After Width: | Height: | Size: 165 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M3 7h10v2H3z" fill="#636363" fill-rule="evenodd"/></svg>
|
||||||
|
After Width: | Height: | Size: 148 B |
@@ -22,6 +22,7 @@ import { ElementType } from "../../dataset/enum/Element"
|
|||||||
import { ImageParticle } from "./particle/ImageParticle"
|
import { ImageParticle } from "./particle/ImageParticle"
|
||||||
import { TextParticle } from "./particle/TextParticle"
|
import { TextParticle } from "./particle/TextParticle"
|
||||||
import { PageNumber } from "./frame/PageNumber"
|
import { PageNumber } from "./frame/PageNumber"
|
||||||
|
import { GlobalObserver } from "../observer/GlobalObserver"
|
||||||
|
|
||||||
export class Draw {
|
export class Draw {
|
||||||
|
|
||||||
@@ -52,6 +53,8 @@ export class Draw {
|
|||||||
private rowList: IRow[]
|
private rowList: IRow[]
|
||||||
private painterStyle: IElementStyle | null
|
private painterStyle: IElementStyle | null
|
||||||
private searchMatchList: number[][] | null
|
private searchMatchList: number[][] | null
|
||||||
|
private visiblePageNoList: number[]
|
||||||
|
private intersectionPageNo: number
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
container: HTMLDivElement,
|
container: HTMLDivElement,
|
||||||
@@ -82,6 +85,7 @@ export class Draw {
|
|||||||
this.imageParticle = new ImageParticle(this)
|
this.imageParticle = new ImageParticle(this)
|
||||||
this.textParticle = new TextParticle(this)
|
this.textParticle = new TextParticle(this)
|
||||||
this.pageNumber = new PageNumber(this)
|
this.pageNumber = new PageNumber(this)
|
||||||
|
new GlobalObserver(this)
|
||||||
|
|
||||||
const canvasEvent = new CanvasEvent(this)
|
const canvasEvent = new CanvasEvent(this)
|
||||||
this.cursor = new Cursor(this, canvasEvent)
|
this.cursor = new Cursor(this, canvasEvent)
|
||||||
@@ -94,6 +98,8 @@ export class Draw {
|
|||||||
this.rowList = []
|
this.rowList = []
|
||||||
this.painterStyle = null
|
this.painterStyle = null
|
||||||
this.searchMatchList = null
|
this.searchMatchList = null
|
||||||
|
this.visiblePageNoList = []
|
||||||
|
this.intersectionPageNo = 0
|
||||||
|
|
||||||
this.render({ isSetCursor: false })
|
this.render({ isSetCursor: false })
|
||||||
}
|
}
|
||||||
@@ -106,6 +112,28 @@ export class Draw {
|
|||||||
return this.pageContainer
|
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 {
|
public getPageNo(): number {
|
||||||
return this.pageNo
|
return this.pageNo
|
||||||
}
|
}
|
||||||
@@ -467,6 +495,13 @@ export class Draw {
|
|||||||
self.render({ curIndex, isSubmitHistory: false })
|
self.render({ curIndex, isSubmitHistory: false })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 页面改变
|
||||||
|
setTimeout(() => {
|
||||||
|
if (this.listener.pageSizeChange) {
|
||||||
|
this.listener.pageSizeChange(pageRowList.length)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,22 @@
|
|||||||
import { IRangeStyleChange } from "../../interface/Listener"
|
import {
|
||||||
|
IIntersectionPageNoChange,
|
||||||
|
IPageSizeChange,
|
||||||
|
IRangeStyleChange,
|
||||||
|
IVisiblePageNoListChange
|
||||||
|
} from "../../interface/Listener"
|
||||||
|
|
||||||
export class Listener {
|
export class Listener {
|
||||||
|
|
||||||
public rangeStyleChange: IRangeStyleChange | null
|
public rangeStyleChange: IRangeStyleChange | null
|
||||||
|
public visiblePageNoListChange: IVisiblePageNoListChange | null
|
||||||
|
public intersectionPageNoChange: IIntersectionPageNoChange | null
|
||||||
|
public pageSizeChange: IPageSizeChange | null
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.rangeStyleChange = null
|
this.rangeStyleChange = null
|
||||||
|
this.visiblePageNoListChange = null
|
||||||
|
this.intersectionPageNoChange = null
|
||||||
|
this.pageSizeChange = null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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<IEditorOption>
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export enum EditorComponent {
|
export enum EditorComponent {
|
||||||
MENU = 'menu',
|
MENU = 'menu',
|
||||||
MAIN = 'main'
|
MAIN = 'main',
|
||||||
|
FOOTER = 'footer'
|
||||||
}
|
}
|
||||||
@@ -16,3 +16,9 @@ export interface IRangeStype {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type IRangeStyleChange = (payload: IRangeStype) => void
|
export type IRangeStyleChange = (payload: IRangeStype) => void
|
||||||
|
|
||||||
|
export type IVisiblePageNoListChange = (payload: number[]) => void
|
||||||
|
|
||||||
|
export type IIntersectionPageNoChange = (payload: number) => void
|
||||||
|
|
||||||
|
export type IPageSizeChange = (payload: number) => void
|
||||||
|
|||||||
+13
@@ -282,4 +282,17 @@ window.onload = function () {
|
|||||||
payload.painter ? painterDom.classList.add('active') : painterDom.classList.remove('active')
|
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<HTMLSpanElement>('.page-no-list')!.innerText = text
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.listener.pageSizeChange = function (payload) {
|
||||||
|
document.querySelector<HTMLSpanElement>('.page-size')!.innerText = `${payload}`
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.listener.intersectionPageNoChange = function (payload) {
|
||||||
|
document.querySelector<HTMLSpanElement>('.page-no')!.innerText = `${payload + 1}`
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -313,3 +345,61 @@ ul {
|
|||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
box-shadow: rgb(158 161 165 / 40%) 0px 2px 12px 0px;
|
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');
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user