feat:add continuity page mode
This commit is contained in:
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><g transform="translate(2 1)"><rect stroke="#3D4757" x=".5" y=".5" width="11" height="8" rx="1"/><path fill="#3D4757" fill-rule="nonzero" d="M2 3h4v1H2zm0 2h8v1H2z"/></g><g fill="#3D4757" fill-rule="nonzero"><path d="M14 15h-1v-5H3v5H2V9h12v6z"/><path d="M4 12h4v1H4zm0 2h8v1H4z"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 413 B |
@@ -1,5 +1,5 @@
|
||||
import { IElement } from '../..'
|
||||
import { EditorMode } from '../../dataset/enum/Editor'
|
||||
import { EditorMode, PageMode } from '../../dataset/enum/Editor'
|
||||
import { RowFlex } from '../../dataset/enum/Row'
|
||||
import { IDrawImagePayload, IPainterOptions } from '../../interface/Draw'
|
||||
import { IEditorResult } from '../../interface/Editor'
|
||||
@@ -57,6 +57,7 @@ export class Command {
|
||||
private static print: Function
|
||||
private static getImage: Function
|
||||
private static getValue: Function
|
||||
private static pageMode: Function
|
||||
private static pageScaleRecovery: Function
|
||||
private static pageScaleMinus: Function
|
||||
private static pageScaleAdd: Function
|
||||
@@ -111,6 +112,7 @@ export class Command {
|
||||
Command.print = adapt.print.bind(adapt)
|
||||
Command.getImage = adapt.getImage.bind(adapt)
|
||||
Command.getValue = adapt.getValue.bind(adapt)
|
||||
Command.pageMode = adapt.pageMode.bind(adapt)
|
||||
Command.pageScaleRecovery = adapt.pageScaleRecovery.bind(adapt)
|
||||
Command.pageScaleMinus = adapt.pageScaleMinus.bind(adapt)
|
||||
Command.pageScaleAdd = adapt.pageScaleAdd.bind(adapt)
|
||||
@@ -313,7 +315,11 @@ export class Command {
|
||||
return Command.getValue()
|
||||
}
|
||||
|
||||
// 页面缩放
|
||||
// 页面模式、页面缩放
|
||||
public executePageMode(payload: PageMode) {
|
||||
return Command.pageMode(payload)
|
||||
}
|
||||
|
||||
public executePageScaleRecovery() {
|
||||
return Command.pageScaleRecovery()
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { WRAP, ZERO } from '../../dataset/constant/Common'
|
||||
import { EDITOR_ELEMENT_STYLE_ATTR } from '../../dataset/constant/Element'
|
||||
import { defaultWatermarkOption } from '../../dataset/constant/Watermark'
|
||||
import { ControlComponent } from '../../dataset/enum/Control'
|
||||
import { EditorContext, EditorMode } from '../../dataset/enum/Editor'
|
||||
import { EditorContext, EditorMode, PageMode } from '../../dataset/enum/Editor'
|
||||
import { ElementType } from '../../dataset/enum/Element'
|
||||
import { ElementStyleKey } from '../../dataset/enum/ElementStyle'
|
||||
import { RowFlex } from '../../dataset/enum/Row'
|
||||
@@ -1243,6 +1243,10 @@ export class CommandAdapt {
|
||||
return this.draw.getValue()
|
||||
}
|
||||
|
||||
public pageMode(payload: PageMode) {
|
||||
this.draw.setPageMode(payload)
|
||||
}
|
||||
|
||||
public pageScaleRecovery() {
|
||||
const { scale } = this.options
|
||||
if (scale !== 1) {
|
||||
|
||||
@@ -34,7 +34,7 @@ import { SubscriptParticle } from './particle/Subscript'
|
||||
import { SeparatorParticle } from './particle/Separator'
|
||||
import { PageBreakParticle } from './particle/PageBreak'
|
||||
import { Watermark } from './frame/Watermark'
|
||||
import { EditorMode } from '../../dataset/enum/Editor'
|
||||
import { EditorMode, PageMode } from '../../dataset/enum/Editor'
|
||||
import { Control } from './control/Control'
|
||||
import { zipElementList } from '../../utils/element'
|
||||
import { CheckboxParticle } from './particle/CheckboxParticle'
|
||||
@@ -97,7 +97,7 @@ export class Draw {
|
||||
this.pageList = []
|
||||
this.ctxList = []
|
||||
this.pageNo = 0
|
||||
this.mode = options.defaultMode
|
||||
this.mode = options.mode
|
||||
this.options = options
|
||||
this.elementList = elementList
|
||||
this.listener = listener
|
||||
@@ -168,6 +168,16 @@ export class Draw {
|
||||
return Math.floor(this.options.height * this.options.scale)
|
||||
}
|
||||
|
||||
public getCanvasWidth(): number {
|
||||
const page = this.getPage()
|
||||
return page.width
|
||||
}
|
||||
|
||||
public getCanvasHeight(): number {
|
||||
const page = this.getPage()
|
||||
return page.height
|
||||
}
|
||||
|
||||
public getInnerWidth(): number {
|
||||
const width = this.getWidth()
|
||||
const margins = this.getMargins()
|
||||
@@ -394,6 +404,26 @@ export class Draw {
|
||||
})
|
||||
}
|
||||
|
||||
public setPageMode(payload: PageMode) {
|
||||
if (!payload || this.options.pageMode === payload) return
|
||||
this.options.pageMode = payload
|
||||
// 纸张大小重置
|
||||
if (payload === PageMode.PAGING) {
|
||||
const { height } = this.options
|
||||
const dpr = window.devicePixelRatio
|
||||
const canvas = this.pageList[0]
|
||||
canvas.style.height = `${height}px`
|
||||
canvas.height = height * dpr
|
||||
}
|
||||
this.render({ isSubmitHistory: false, isSetCursor: false })
|
||||
// 回调
|
||||
setTimeout(() => {
|
||||
if (this.listener.pageModeChange) {
|
||||
this.listener.pageModeChange(payload)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public setPageScale(payload: number) {
|
||||
this.options.scale = payload
|
||||
const width = this.getWidth()
|
||||
@@ -855,12 +885,12 @@ export class Draw {
|
||||
}
|
||||
|
||||
private _drawPage(positionList: IElementPosition[], rowList: IRow[], pageNo: number) {
|
||||
const width = this.getWidth()
|
||||
const height = this.getHeight()
|
||||
const { pageMode } = this.options
|
||||
const margins = this.getMargins()
|
||||
const innerWidth = this.getInnerWidth()
|
||||
const ctx = this.ctxList[pageNo]
|
||||
ctx.clearRect(0, 0, width, height)
|
||||
const pageDom = this.pageList[pageNo]
|
||||
ctx.clearRect(0, 0, pageDom.width, pageDom.height)
|
||||
// 绘制背景
|
||||
this.background.render(ctx)
|
||||
// 绘制页边距
|
||||
@@ -891,12 +921,13 @@ export class Draw {
|
||||
this.search.render(ctx, pageNo)
|
||||
}
|
||||
// 绘制水印
|
||||
if (this.options.watermark.data) {
|
||||
if (pageMode !== PageMode.CONTINUITY && this.options.watermark.data) {
|
||||
this.waterMark.render(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
public render(payload?: IDrawOption) {
|
||||
const { pageMode } = this.options
|
||||
const {
|
||||
isSubmitHistory = true,
|
||||
isSetCursor = true,
|
||||
@@ -922,15 +953,32 @@ export class Draw {
|
||||
let pageHeight = marginHeight
|
||||
let pageNo = 0
|
||||
const pageRowList: IRow[][] = [[]]
|
||||
for (let i = 0; i < this.rowList.length; i++) {
|
||||
const row = this.rowList[i]
|
||||
if (row.height + pageHeight > height || this.rowList[i - 1]?.isPageBreak) {
|
||||
pageHeight = marginHeight + row.height
|
||||
pageRowList.push([row])
|
||||
pageNo++
|
||||
if (pageMode === PageMode.CONTINUITY) {
|
||||
pageRowList[0] = this.rowList
|
||||
// 重置高度
|
||||
pageHeight += this.rowList.reduce((pre, cur) => pre + cur.height, 0)
|
||||
const dpr = window.devicePixelRatio
|
||||
const pageDom = this.pageList[0]
|
||||
const pageDomHeight = Number(pageDom.style.height.replace('px', ''))
|
||||
if (pageHeight > pageDomHeight) {
|
||||
pageDom.style.height = `${pageHeight}px`
|
||||
pageDom.height = pageHeight * dpr
|
||||
} else {
|
||||
pageHeight += row.height
|
||||
pageRowList[pageNo].push(row)
|
||||
const reduceHeight = pageHeight < height ? height : pageHeight
|
||||
pageDom.style.height = `${reduceHeight}px`
|
||||
pageDom.height = reduceHeight * dpr
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < this.rowList.length; i++) {
|
||||
const row = this.rowList[i]
|
||||
if (row.height + pageHeight > height || this.rowList[i - 1]?.isPageBreak) {
|
||||
pageHeight = marginHeight + row.height
|
||||
pageRowList.push([row])
|
||||
pageNo++
|
||||
} else {
|
||||
pageHeight += row.height
|
||||
pageRowList[pageNo].push(row)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 绘制元素
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { PageMode } from '../../../dataset/enum/Editor'
|
||||
import { IEditorOption } from '../../../interface/Editor'
|
||||
import { Draw } from '../Draw'
|
||||
|
||||
@@ -12,9 +13,11 @@ export class Margin {
|
||||
}
|
||||
|
||||
public render(ctx: CanvasRenderingContext2D) {
|
||||
const { marginIndicatorColor } = this.options
|
||||
const { marginIndicatorColor, pageMode } = this.options
|
||||
const width = this.draw.getWidth()
|
||||
const height = this.draw.getHeight()
|
||||
const height = pageMode === PageMode.CONTINUITY
|
||||
? this.draw.getCanvasHeight()
|
||||
: this.draw.getHeight()
|
||||
const margins = this.draw.getMargins()
|
||||
const marginIndicatorSize = this.draw.getMarginIndicatorSize()
|
||||
ctx.save()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { PageMode } from '../../../dataset/enum/Editor'
|
||||
import { IEditorOption } from '../../../interface/Editor'
|
||||
import { Draw } from '../Draw'
|
||||
|
||||
@@ -12,9 +13,11 @@ export class PageNumber {
|
||||
}
|
||||
|
||||
public render(ctx: CanvasRenderingContext2D, pageNo: number) {
|
||||
const { pageNumberSize, pageNumberFont, scale } = this.options
|
||||
const { pageNumberSize, pageNumberFont, scale, pageMode } = this.options
|
||||
const width = this.draw.getWidth()
|
||||
const height = this.draw.getHeight()
|
||||
const height = pageMode === PageMode.CONTINUITY
|
||||
? this.draw.getCanvasHeight()
|
||||
: this.draw.getHeight()
|
||||
const pageNumberBottom = this.draw.getPageNumberBottom()
|
||||
ctx.save()
|
||||
ctx.fillStyle = '#00000'
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
IContentChange,
|
||||
IControlChange,
|
||||
IIntersectionPageNoChange,
|
||||
IPageModeChange,
|
||||
IPageScaleChange,
|
||||
IPageSizeChange,
|
||||
IRangeStyleChange,
|
||||
@@ -19,6 +20,7 @@ export class Listener {
|
||||
public saved: ISaved | null
|
||||
public contentChange: IContentChange | null
|
||||
public controlChange: IControlChange | null
|
||||
public pageModeChange: IPageModeChange | null
|
||||
|
||||
constructor() {
|
||||
this.rangeStyleChange = null
|
||||
@@ -29,6 +31,7 @@ export class Listener {
|
||||
this.saved = null
|
||||
this.contentChange = null
|
||||
this.controlChange = null
|
||||
this.pageModeChange = null
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,4 +16,9 @@ export enum EditorMode {
|
||||
EDIT = 'edit',
|
||||
CLEAN = 'clean',
|
||||
READONLY = 'readonly'
|
||||
}
|
||||
|
||||
export enum PageMode {
|
||||
PAGING = 'paging',
|
||||
CONTINUITY = 'continuity'
|
||||
}
|
||||
+5
-3
@@ -13,7 +13,7 @@ import { globalMenus } from './core/contextmenu/menus/globalMenus'
|
||||
import { ContextMenu } from './core/contextmenu/ContextMenu'
|
||||
import { tableMenus } from './core/contextmenu/menus/tableMenus'
|
||||
import { IContextMenuContext, IRegisterContextMenu } from './interface/contextmenu/ContextMenu'
|
||||
import { EditorComponent, EditorMode } from './dataset/enum/Editor'
|
||||
import { EditorComponent, EditorMode, PageMode } from './dataset/enum/Editor'
|
||||
import { EDITOR_COMPONENT } from './dataset/constant/Editor'
|
||||
import { IHeader } from './interface/Header'
|
||||
import { IWatermark } from './interface/Watermark'
|
||||
@@ -51,7 +51,7 @@ export default class Editor {
|
||||
}
|
||||
|
||||
const editorOptions: DeepRequired<IEditorOption> = {
|
||||
defaultMode: EditorMode.EDIT,
|
||||
mode: EditorMode.EDIT,
|
||||
defaultType: 'TEXT',
|
||||
defaultFont: 'Yahei',
|
||||
defaultSize: 16,
|
||||
@@ -77,6 +77,7 @@ export default class Editor {
|
||||
marginIndicatorSize: 35,
|
||||
marginIndicatorColor: '#BABABA',
|
||||
margins: [100, 120, 100, 120],
|
||||
pageMode: PageMode.PAGING,
|
||||
tdPadding: 5,
|
||||
defaultTdHeight: 40,
|
||||
defaultHyperlinkColor: '#0000FF',
|
||||
@@ -116,7 +117,8 @@ export {
|
||||
ElementType,
|
||||
ControlType,
|
||||
EditorComponent,
|
||||
EDITOR_COMPONENT
|
||||
EDITOR_COMPONENT,
|
||||
PageMode
|
||||
}
|
||||
|
||||
// 对外类型
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { IElement } from '..'
|
||||
import { EditorMode } from '../dataset/enum/Editor'
|
||||
import { EditorMode, PageMode } from '../dataset/enum/Editor'
|
||||
import { ICheckboxOption } from './Checkbox'
|
||||
import { IControlOption } from './Control'
|
||||
import { IHeader } from './Header'
|
||||
import { IWatermark } from './Watermark'
|
||||
|
||||
export interface IEditorOption {
|
||||
defaultMode?: EditorMode;
|
||||
mode?: EditorMode;
|
||||
defaultType?: string;
|
||||
defaultFont?: string;
|
||||
defaultSize?: number;
|
||||
@@ -32,6 +32,7 @@ export interface IEditorOption {
|
||||
marginIndicatorSize?: number;
|
||||
marginIndicatorColor?: string,
|
||||
margins?: [top: number, right: number, bottom: number, left: number],
|
||||
pageMode?: PageMode;
|
||||
tdPadding?: number;
|
||||
defaultTdHeight?: number;
|
||||
defaultHyperlinkColor?: string;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ElementType } from '..'
|
||||
import { ElementType, PageMode } from '..'
|
||||
import { RowFlex } from '../dataset/enum/Row'
|
||||
import { IControl } from './Control'
|
||||
import { IEditorResult } from './Editor'
|
||||
@@ -34,4 +34,6 @@ export type ISaved = (payload: IEditorResult) => void
|
||||
|
||||
export type IContentChange = () => void
|
||||
|
||||
export type IControlChange = (payload: IControl | null) => void
|
||||
export type IControlChange = (payload: IControl | null) => void
|
||||
|
||||
export type IPageModeChange = (payload: PageMode) => void
|
||||
+18
-2
@@ -1,7 +1,7 @@
|
||||
import { data, options } from './mock'
|
||||
import './style.css'
|
||||
import prism from 'prismjs'
|
||||
import Editor, { ControlType, EditorMode, ElementType, IElement } from './editor'
|
||||
import Editor, { ControlType, EditorMode, ElementType, IElement, PageMode } from './editor'
|
||||
import { Dialog } from './components/dialog/Dialog'
|
||||
import { formatPrismToken } from './utils/prism'
|
||||
|
||||
@@ -586,7 +586,17 @@ window.onload = function () {
|
||||
instance.command.executePrint()
|
||||
}
|
||||
|
||||
// 6. 纸张缩放
|
||||
// 6. 页面模式 | 纸张缩放
|
||||
const pageModeDom = document.querySelector<HTMLDivElement>('.page-mode')!
|
||||
const pageModeOptionsDom = pageModeDom.querySelector<HTMLDivElement>('.options')!
|
||||
pageModeDom.onclick = function () {
|
||||
pageModeOptionsDom.classList.toggle('visible')
|
||||
}
|
||||
pageModeOptionsDom.onclick = function (evt) {
|
||||
const li = evt.target as HTMLLIElement
|
||||
instance.command.executePageMode(<PageMode>li.dataset.pageMode!)
|
||||
}
|
||||
|
||||
document.querySelector<HTMLDivElement>('.page-scale-percentage')!.onclick = function () {
|
||||
console.log('page-scale-recovery')
|
||||
instance.command.executePageScaleRecovery()
|
||||
@@ -738,6 +748,12 @@ window.onload = function () {
|
||||
})
|
||||
}
|
||||
|
||||
instance.listener.pageModeChange = function (payload) {
|
||||
const activeMode = pageModeOptionsDom.querySelector<HTMLLIElement>(`[data-page-mode='${payload}']`)!
|
||||
pageModeOptionsDom.querySelectorAll('li').forEach(li => li.classList.remove('active'))
|
||||
activeMode.classList.add('active')
|
||||
}
|
||||
|
||||
instance.listener.saved = function (payload) {
|
||||
console.log('elementList: ', payload)
|
||||
}
|
||||
|
||||
+54
-1
@@ -551,7 +551,6 @@ ul {
|
||||
justify-content: space-between;
|
||||
background: #f2f4f7;
|
||||
z-index: 9;
|
||||
overflow: hidden;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
@@ -560,6 +559,60 @@ ul {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.footer>div:first-child {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer .page-mode {
|
||||
padding: 1px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.footer .page-mode i {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
background-image: url('./assets/images/page-mode.svg');
|
||||
}
|
||||
|
||||
.footer .page-mode .options {
|
||||
width: 70px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 25px;
|
||||
padding: 10px;
|
||||
background: #fff;
|
||||
font-size: 14px;
|
||||
box-shadow: 0 2px 12px 0 rgb(56 56 56 / 20%);
|
||||
border: 1px solid #e2e6ed;
|
||||
border-radius: 2px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.footer .page-mode .options.visible {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.footer .page-mode .options li {
|
||||
padding: 5px;
|
||||
margin: 5px 0;
|
||||
user-select: none;
|
||||
transition: all .3s;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.footer .page-mode .options li:hover {
|
||||
background-color: #ebecef;
|
||||
}
|
||||
|
||||
.footer .page-mode .options li.active {
|
||||
background-color: #e2e6ed;
|
||||
}
|
||||
|
||||
.footer>div:first-child>span {
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
|
||||
Reference in New Issue
Block a user