feat: add page footer

pr675
Hufe921 3 years ago committed by Hufe
parent 36f3bb42ce
commit 21626cc41b

@ -5,6 +5,7 @@
.ce-resizer-selection>div {
position: absolute;
z-index: 9;
width: 10px;
height: 10px;
box-shadow: 0 1px 4px 0 rgb(0 0 0 / 30%);

@ -1,4 +1,4 @@
.ce-header-indicator>div {
.ce-zone-indicator>div {
padding: 3px 6px;
color: #000000;
font-size: 12px;
@ -7,27 +7,28 @@
transform-origin: 0 0;
}
.ce-header-indicator-border__top,
.ce-header-indicator-border__bottom,
.ce-header-indicator-border__left,
.ce-header-indicator-border__right {
.ce-zone-indicator-border__top,
.ce-zone-indicator-border__bottom,
.ce-zone-indicator-border__left,
.ce-zone-indicator-border__right {
display: block;
position: absolute;
z-index: 0;
}
.ce-header-indicator-border__top {
.ce-zone-indicator-border__top {
border-top: 2px dashed rgb(238, 238, 238);
}
.ce-header-indicator-border__bottom {
.ce-zone-indicator-border__bottom {
border-top: 2px dashed rgb(238, 238, 238);
width: 100%;
}
.ce-header-indicator-border__left {
.ce-zone-indicator-border__left {
border-left: 2px dashed rgb(238, 238, 238);
}
.ce-header-indicator-border__right {
.ce-zone-indicator-border__right {
border-right: 2px dashed rgb(238, 238, 238);
}

@ -51,6 +51,7 @@ import { EDITOR_COMPONENT, EDITOR_PREFIX } from '../../dataset/constant/Editor'
import { I18n } from '../i18n/I18n'
import { ImageObserver } from '../observer/ImageObserver'
import { Zone } from '../zone/Zone'
import { Footer } from './frame/Footer'
export class Draw {
@ -89,6 +90,7 @@ export class Draw {
private pageNumber: PageNumber
private waterMark: Watermark
private header: Header
private footer: Footer
private hyperlinkParticle: HyperlinkParticle
private dateParticle: DateParticle
private separatorParticle: SeparatorParticle
@ -152,6 +154,7 @@ export class Draw {
this.pageNumber = new PageNumber(this)
this.waterMark = new Watermark(this)
this.header = new Header(this)
this.footer = new Footer(this)
this.hyperlinkParticle = new HyperlinkParticle(this)
this.dateParticle = new DateParticle(this)
this.separatorParticle = new SeparatorParticle()
@ -217,9 +220,14 @@ export class Draw {
public getMainHeight(): number {
const pageHeight = this.getHeight()
return pageHeight - this.getMainOuterHeight()
}
public getMainOuterHeight(): number {
const margins = this.getMargins()
const extraHeight = this.header.getExtraHeight()
return pageHeight - margins[0] - margins[2] - extraHeight
const headerExtraHeight = this.header.getExtraHeight()
const footerExtraHeight = this.footer.getExtraHeight()
return margins[0] + margins[2] + headerExtraHeight + footerExtraHeight
}
public getCanvasWidth(pageNo = -1): number {
@ -385,9 +393,13 @@ export class Draw {
public getOriginalElementList() {
const zoneManager = this.getZone()
return zoneManager.isHeaderActive()
? this.header.getElementList()
: this.elementList
if (zoneManager.isHeaderActive()) {
return this.header.getElementList()
}
if (zoneManager.isFooterActive()) {
return this.footer.getElementList()
}
return this.elementList
}
public getOriginalMainElementList(): IElement[] {
@ -468,6 +480,10 @@ export class Draw {
return this.header
}
public getFooter(): Footer {
return this.footer
}
public getHyperlinkParticle(): HyperlinkParticle {
return this.hyperlinkParticle
}
@ -646,7 +662,8 @@ export class Draw {
// 数据
const data: IEditorData = {
header: zipElementList(this.headerElementList),
main: zipElementList(this.elementList)
main: zipElementList(this.elementList),
footer: zipElementList(this.footerElementList)
}
return {
version,
@ -803,10 +820,8 @@ export class Draw {
metrics.boundingBoxDescent = elementHeight
metrics.boundingBoxAscent = 0
// 表格分页处理(拆分表格)
const margins = this.getMargins()
const height = this.getHeight()
const headerExtraHeight = this.header.getExtraHeight()
const marginHeight = margins[0] + margins[2] + headerExtraHeight
const marginHeight = this.getMainOuterHeight()
let curPagePreHeight = marginHeight
for (let r = 0; r < rowList.length; r++) {
const row = rowList[r]
@ -973,9 +988,7 @@ export class Draw {
const pageRowList: IRow[][] = [[]]
const { pageMode } = this.options
const height = this.getHeight()
const margins = this.getMargins()
const headerExtraHeight = this.header.getExtraHeight()
const marginHeight = margins[0] + margins[2] + headerExtraHeight
const marginHeight = this.getMainOuterHeight()
let pageHeight = marginHeight
let pageNo = 0
if (pageMode === PageMode.CONTINUITY) {
@ -1196,8 +1209,8 @@ export class Draw {
const { inactiveAlpha, pageMode } = this.options
const innerWidth = this.getInnerWidth()
const ctx = this.ctxList[pageNo]
// 判断当前激活区域-激活页眉时主题元素透明度降低
ctx.globalAlpha = this.zone.isHeaderActive() ? inactiveAlpha : 1
// 判断当前激活区域-非正文区域时元素透明度降低
ctx.globalAlpha = !this.zone.isMainActive() ? inactiveAlpha : 1
this._clearPage(pageNo)
// 绘制背景
this.background.render(ctx)
@ -1218,6 +1231,8 @@ export class Draw {
this.header.render(ctx, pageNo)
// 绘制页码
this.pageNumber.render(ctx, pageNo)
// 绘制页脚
this.footer.render(ctx, pageNo)
// 搜索匹配绘制
if (this.search.getSearchKeyword()) {
this.search.render(ctx, pageNo)
@ -1236,7 +1251,6 @@ export class Draw {
entries.forEach(entry => {
if (entry.isIntersecting) {
const index = Number((<HTMLCanvasElement>entry.target).dataset.index)
this.header.render(this.ctxList[index], index)
this._drawPage({
elementList,
positionList,
@ -1278,6 +1292,8 @@ export class Draw {
if (isCompute) {
// 页眉信息
this.header.compute()
// 页脚信息
this.footer.compute()
// 行信息
this.rowList = this.computeRowList(innerWidth, this.elementList)
// 页面信息
@ -1338,6 +1354,7 @@ export class Draw {
const self = this
const oldElementList = deepClone(this.elementList)
const oldHeaderElementList = deepClone(this.header.getElementList())
const oldFooterElementList = deepClone(this.footer.getElementList())
const { startIndex, endIndex } = this.range.getRange()
const pageNo = this.pageNo
const oldPositionContext = deepClone(positionContext)
@ -1345,8 +1362,9 @@ export class Draw {
this.historyManager.execute(function () {
self.zone.setZone(zone)
self.setPageNo(pageNo)
self.position.setPositionContext(oldPositionContext)
self.header.setElementList(oldHeaderElementList)
self.position.setPositionContext(deepClone(oldPositionContext))
self.header.setElementList(deepClone(oldHeaderElementList))
self.footer.setElementList(deepClone(oldFooterElementList))
self.elementList = deepClone(oldElementList)
self.range.setRange(startIndex, endIndex)
self.render({ curIndex, isSubmitHistory: false })
@ -1359,8 +1377,8 @@ export class Draw {
this.tableTool.render()
}
// 页眉指示器重新渲染
if (isCompute && this.zone.isHeaderActive()) {
this.zone.drawHeaderZoneIndicator()
if (isCompute && !this.zone.isMainActive()) {
this.zone.drawZoneIndicator()
}
// 页面尺寸改变
if (this.listener.pageSizeChange) {

@ -0,0 +1,134 @@
import { maxHeightRadioMapping } from '../../../dataset/constant/Common'
import { EditorZone } from '../../../dataset/enum/Editor'
import { DeepRequired } from '../../../interface/Common'
import { IEditorOption } from '../../../interface/Editor'
import { IElement, IElementPosition } from '../../../interface/Element'
import { IRow } from '../../../interface/Row'
import { Position } from '../../position/Position'
import { Draw } from '../Draw'
export class Footer {
private draw: Draw
private position: Position
private options: DeepRequired<IEditorOption>
private elementList: IElement[]
private rowList: IRow[]
private positionList: IElementPosition[]
constructor(draw: Draw) {
this.draw = draw
this.position = draw.getPosition()
this.options = draw.getOptions()
this.elementList = draw.getFooterElementList()
this.rowList = []
this.positionList = []
}
public setElementList(elementList: IElement[]) {
this.elementList = elementList
}
public getElementList(): IElement[] {
return this.elementList
}
public getPositionList(): IElementPosition[] {
return this.positionList
}
public compute() {
this._recovery()
this._computeRowList()
this._computePositionList()
}
private _recovery() {
this.rowList = []
this.positionList = []
}
private _computeRowList() {
const innerWidth = this.draw.getInnerWidth()
this.rowList = this.draw.computeRowList(innerWidth, this.elementList)
}
private _computePositionList() {
const footerBottom = this.getFooterBottom()
const innerWidth = this.draw.getInnerWidth()
const margins = this.draw.getMargins()
const startX = margins[3]
// 页面高度 - 页脚顶部距离页面底部高度
const pageHeight = this.draw.getHeight()
const footerHeight = this.getHeight()
const startY = pageHeight - footerBottom - footerHeight
this.position.computePageRowPosition({
positionList: this.positionList,
rowList: this.rowList,
pageNo: 0,
startIndex: 0,
startX,
startY,
innerWidth
})
}
public getFooterBottom(): number {
const { footer: { bottom }, scale } = this.options
return Math.floor(bottom * scale)
}
public getMaxHeight(): number {
const { footer: { maxHeightRadio } } = this.options
const height = this.draw.getHeight()
return Math.floor(height * maxHeightRadioMapping[maxHeightRadio])
}
public getHeight(): number {
const maxHeight = this.getMaxHeight()
const rowHeight = this.getRowHeight()
return rowHeight > maxHeight ? maxHeight : rowHeight
}
public getRowHeight(): number {
return this.rowList.reduce((pre, cur) => pre + cur.height, 0)
}
public getExtraHeight(): number {
// 页脚下边距 + 实际高 - 页面上边距
const margins = this.draw.getMargins()
const footerHeight = this.getHeight()
const footerBottom = this.getFooterBottom()
const extraHeight = footerBottom + footerHeight - margins[2]
return extraHeight <= 0 ? 0 : extraHeight
}
public render(ctx: CanvasRenderingContext2D, pageNo: number) {
ctx.globalAlpha = 1
const innerWidth = this.draw.getInnerWidth()
const maxHeight = this.getMaxHeight()
// 超出最大高度不渲染
const rowList: IRow[] = []
let curRowHeight = 0
for (let r = 0; r < this.rowList.length; r++) {
const row = this.rowList[r]
if (curRowHeight + row.height > maxHeight) {
break
}
rowList.push(row)
curRowHeight += row.height
}
this.draw.drawRow(ctx, {
elementList: this.elementList,
positionList: this.positionList,
rowList,
pageNo,
startIndex: 0,
innerWidth,
zone: EditorZone.FOOTER
})
}
}

@ -1,4 +1,4 @@
import { maxHeightRadioMapping } from '../../../dataset/constant/Header'
import { maxHeightRadioMapping } from '../../../dataset/constant/Common'
import { EditorZone } from '../../../dataset/enum/Editor'
import { DeepRequired } from '../../../interface/Common'
import { IEditorOption } from '../../../interface/Editor'

@ -32,7 +32,7 @@ export class PageNumber {
const margins = this.draw.getMargins()
const { width: textWidth } = ctx.measureText(text)
if (rowFlex === RowFlex.CENTER) {
x = (width + textWidth) / 2
x = (width - textWidth) / 2
} else if (rowFlex === RowFlex.RIGHT) {
x = width - textWidth - margins[1]
} else {

@ -262,9 +262,9 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
} else if (evt.key === KeyMap.ESC) {
// 退出格式刷
host.clearPainterStyle()
// 退出页眉编辑
// 退出页眉页脚编辑
const zoneManager = draw.getZone()
if (zoneManager.isHeaderActive()) {
if (!zoneManager.isMainActive()) {
zoneManager.setZone(EditorZone.MAIN)
}
evt.preventDefault()

@ -48,8 +48,15 @@ export class Position {
public getOriginalPositionList(): IElementPosition[] {
const zoneManager = this.draw.getZone()
const header = this.draw.getHeader()
return zoneManager.isHeaderActive() ? header.getPositionList() : this.positionList
if (zoneManager.isHeaderActive()) {
const header = this.draw.getHeader()
return header.getPositionList()
}
if (zoneManager.isFooterActive()) {
const footer = this.draw.getFooter()
return footer.getPositionList()
}
return this.positionList
}
public getOriginalMainPositionList(): IElementPosition[] {
@ -209,7 +216,8 @@ export class Position {
}
const zoneManager = this.draw.getZone()
const curPageNo = this.draw.getPageNo()
const positionNo = zoneManager.isMainActive() ? curPageNo : 0
const isMainActive = zoneManager.isMainActive()
const positionNo = isMainActive ? curPageNo : 0
for (let j = 0; j < positionList.length; j++) {
const { index, pageNo, coordinate: { leftTop, rightTop, leftBottom } } = positionList[j]
if (positionNo !== pageNo) continue
@ -306,15 +314,15 @@ export class Position {
}
}
// 判断所属行是否存在元素
const firstLetterList = positionList.filter(p => p.isLastLetter && p.pageNo === positionNo)
for (let j = 0; j < firstLetterList.length; j++) {
const { index, pageNo, coordinate: { leftTop, leftBottom } } = firstLetterList[j]
const lastLetterList = positionList.filter(p => p.isLastLetter && p.pageNo === positionNo)
for (let j = 0; j < lastLetterList.length; j++) {
const { index, pageNo, coordinate: { leftTop, leftBottom } } = lastLetterList[j]
if (positionNo !== pageNo) continue
if (y > leftTop[1] && y <= leftBottom[1]) {
const isHead = x < this.options.margins[3]
// 是否在头部
if (isHead) {
const headIndex = positionList.findIndex(p => p.pageNo === positionNo && p.rowNo === firstLetterList[j].rowNo)
const headIndex = positionList.findIndex(p => p.pageNo === positionNo && p.rowNo === lastLetterList[j].rowNo)
curPositionIndex = ~headIndex ? headIndex - 1 : index
} else {
curPositionIndex = index
@ -324,18 +332,30 @@ export class Position {
}
}
if (!isLastArea) {
// 判断所属位置是否属于header区域当前位置小于第一行的上边距
if (zoneManager.isMainActive()) {
if (y < firstLetterList[0].coordinate.leftTop[1]) {
const mainLastLetterList = isMainActive
? lastLetterList
: this.getOriginalMainPositionList().filter(p => p.isLastLetter && p.pageNo === positionNo)
const firstPosition = mainLastLetterList[0]
const lastPosition = mainLastLetterList[mainLastLetterList.length - 1]
// 判断所属位置是否属于页眉页脚区域
if (isMainActive) {
// 页眉:当前位置小于第一行的上边距
if (y < firstPosition.coordinate.leftTop[1]) {
return {
index: -1,
zone: EditorZone.HEADER
}
}
}
// 判断所属位置是否属于main区域当前位置大于第一行的上边距
if (zoneManager.isHeaderActive()) {
if (y > firstLetterList[0].coordinate.leftTop[1]) {
// 页脚:当前位置大于最后一行的下边距
if (y > lastPosition.coordinate.leftBottom[1]) {
return {
index: -1,
zone: EditorZone.FOOTER
}
}
} else {
// main区域当前位置大于第一行的上边距 && 小于最后一行的下边距
if (y >= firstPosition.coordinate.leftTop[1] && y <= lastPosition.coordinate.leftBottom[1]) {
return {
index: -1,
zone: EditorZone.MAIN
@ -344,7 +364,7 @@ export class Position {
}
// 当前页最后一行
return {
index: firstLetterList[firstLetterList.length - 1]?.index || positionList.length - 1,
index: lastLetterList[lastLetterList.length - 1]?.index || positionList.length - 1,
}
}
return {

@ -6,6 +6,7 @@ import { I18n } from '../i18n/I18n'
export class Zone {
private readonly INDICATOR_PADDING = 2
private readonly INDICATOR_TITLE_TRANSLATE = [20, 5]
private draw: Draw
@ -14,7 +15,7 @@ export class Zone {
private container: HTMLDivElement
private currentZone: EditorZone
private headerIndicatorContainer: HTMLDivElement | null
private indicatorContainer: HTMLDivElement | null
constructor(draw: Draw) {
this.draw = draw
@ -22,7 +23,7 @@ export class Zone {
this.options = draw.getOptions()
this.container = draw.getContainer()
this.currentZone = EditorZone.MAIN
this.headerIndicatorContainer = null
this.indicatorContainer = null
}
public isHeaderActive(): boolean {
@ -33,6 +34,10 @@ export class Zone {
return this.getZone() === EditorZone.MAIN
}
public isFooterActive(): boolean {
return this.getZone() === EditorZone.FOOTER
}
public getZone(): EditorZone {
return this.currentZone
}
@ -46,74 +51,87 @@ export class Zone {
isSetCursor: false,
isCompute: false
})
// 页眉指示器
if (this.isHeaderActive()) {
this.drawHeaderZoneIndicator()
} else {
this._clearHeaderZoneIndicator()
}
// 指示器
this.drawZoneIndicator()
}
public drawHeaderZoneIndicator() {
this._clearHeaderZoneIndicator()
public drawZoneIndicator() {
this._clearZoneIndicator()
if (!this.isHeaderActive() && !this.isFooterActive()) return
const { scale } = this.options
const isHeaderActive = this.isHeaderActive()
const [offsetX, offsetY] = this.INDICATOR_TITLE_TRANSLATE
this.headerIndicatorContainer = document.createElement('div')
this.headerIndicatorContainer.classList.add(`${EDITOR_PREFIX}-header-indicator`)
const pageList = this.draw.getPageList()
const margins = this.draw.getMargins()
const innerWidth = this.draw.getInnerWidth()
const pageHeight = this.draw.getHeight()
const pageGap = this.draw.getPageGap()
const preY = pageHeight + pageGap
// 创建指示器容器
this.indicatorContainer = document.createElement('div')
this.indicatorContainer.classList.add(`${EDITOR_PREFIX}-zone-indicator`)
// 指示器位置
const header = this.draw.getHeader()
const headerHeight = header.getHeight()
const headerTop = header.getHeaderTop()
const footer = this.draw.getFooter()
const indicatorHeight = isHeaderActive
? header.getHeight()
: footer.getHeight()
const indicatorTop = isHeaderActive
? header.getHeaderTop()
: pageHeight - footer.getFooterBottom() - indicatorHeight
for (let p = 0; p < pageList.length; p++) {
const startY = preY * p + headerTop
const indicatorTitle = document.createElement('div')
const startY = preY * p + indicatorTop
const indicatorLeftX = margins[3] - this.INDICATOR_PADDING
const indicatorRightX = margins[3] + innerWidth + this.INDICATOR_PADDING
const indicatorTopY = isHeaderActive
? startY - this.INDICATOR_PADDING
: startY + indicatorHeight + this.INDICATOR_PADDING
const indicatorBottomY = isHeaderActive
? startY + indicatorHeight + this.INDICATOR_PADDING
: startY - this.INDICATOR_PADDING
// 标题
indicatorTitle.innerText = this.i18n.t('frame.header')
indicatorTitle.style.top = `${startY + headerHeight}px`
const indicatorTitle = document.createElement('div')
indicatorTitle.innerText = this.i18n.t(`frame.${isHeaderActive ? 'header' : 'footer'}`)
indicatorTitle.style.top = `${indicatorBottomY}px`
indicatorTitle.style.transform = `translate(${offsetX * scale}px, ${offsetY * scale}px) scale(${scale})`
this.headerIndicatorContainer.append(indicatorTitle)
this.indicatorContainer.append(indicatorTitle)
// 上边线
const lineTop = document.createElement('span')
lineTop.classList.add(`${EDITOR_PREFIX}-header-indicator-border__top`)
lineTop.style.top = `${startY}px`
lineTop.classList.add(`${EDITOR_PREFIX}-zone-indicator-border__top`)
lineTop.style.top = `${indicatorTopY}px`
lineTop.style.width = `${innerWidth}px`
lineTop.style.marginLeft = `${margins[3]}px`
this.headerIndicatorContainer.append(lineTop)
this.indicatorContainer.append(lineTop)
// 左边线
const lineLeft = document.createElement('span')
lineLeft.classList.add(`${EDITOR_PREFIX}-header-indicator-border__left`)
lineLeft.classList.add(`${EDITOR_PREFIX}-zone-indicator-border__left`)
lineLeft.style.top = `${startY}px`
lineLeft.style.height = `${headerHeight}px`
lineLeft.style.left = `${margins[3]}px`
this.headerIndicatorContainer.append(lineLeft)
lineLeft.style.height = `${indicatorHeight}px`
lineLeft.style.left = `${indicatorLeftX}px`
this.indicatorContainer.append(lineLeft)
// 下边线
const lineBottom = document.createElement('span')
lineBottom.classList.add(`${EDITOR_PREFIX}-header-indicator-border__bottom`)
lineBottom.style.top = `${startY + headerHeight}px`
this.headerIndicatorContainer.append(lineBottom)
lineBottom.classList.add(`${EDITOR_PREFIX}-zone-indicator-border__bottom`)
lineBottom.style.top = `${indicatorBottomY}px`
this.indicatorContainer.append(lineBottom)
// 右边线
const lineRight = document.createElement('span')
lineRight.classList.add(`${EDITOR_PREFIX}-header-indicator-border__right`)
lineRight.classList.add(`${EDITOR_PREFIX}-zone-indicator-border__right`)
lineRight.style.top = `${startY}px`
lineRight.style.height = `${headerHeight}px`
lineRight.style.left = `${margins[3] + innerWidth}px`
this.headerIndicatorContainer.append(lineRight)
lineRight.style.height = `${indicatorHeight}px`
lineRight.style.left = `${indicatorRightX}px`
this.indicatorContainer.append(lineRight)
}
this.container.append(this.headerIndicatorContainer)
this.container.append(this.indicatorContainer)
}
private _clearHeaderZoneIndicator() {
this.headerIndicatorContainer?.remove()
this.headerIndicatorContainer = null
private _clearZoneIndicator() {
this.indicatorContainer?.remove()
this.indicatorContainer = null
}
}

@ -1,4 +1,12 @@
import { MaxHeightRatio } from '../enum/Common'
export const ZERO = '\u200B'
export const WRAP = '\n'
export const HORIZON_TAB = '\t'
export const NBSP = '\u0020'
export const NBSP = '\u0020'
export const maxHeightRadioMapping: Record<MaxHeightRatio, number> = {
[MaxHeightRatio.HALF]: 1 / 2,
[MaxHeightRatio.ONE_THIRD]: 1 / 3,
[MaxHeightRatio.QUARTER]: 1 / 4
}

@ -0,0 +1,7 @@
import { IFooter } from '../../interface/Footer'
import { MaxHeightRatio } from '../enum/Common'
export const defaultFooterOption: Readonly<Required<IFooter>> = {
bottom: 30,
maxHeightRadio: MaxHeightRatio.HALF
}

@ -1,13 +1,7 @@
import { IHeader } from '../../interface/Header'
import { HeaderMaxHeightRatio } from '../enum/Header'
import { MaxHeightRatio } from '../enum/Common'
export const defaultHeaderOption: Readonly<Required<IHeader>> = {
top: 30,
maxHeightRadio: HeaderMaxHeightRatio.HALF
}
export const maxHeightRadioMapping: Record<HeaderMaxHeightRatio, number> = {
[HeaderMaxHeightRatio.HALF]: 1 / 2,
[HeaderMaxHeightRatio.ONE_THIRD]: 1 / 3,
[HeaderMaxHeightRatio.QUARTER]: 1 / 4
maxHeightRadio: MaxHeightRatio.HALF
}

@ -1,4 +1,4 @@
export enum HeaderMaxHeightRatio {
export enum MaxHeightRatio {
HALF = 'half',
ONE_THIRD = 'one-third',
QUARTER = 'quarter'

@ -35,6 +35,9 @@ import { IPageNumber } from './interface/PageNumber'
import { defaultPageNumberOption } from './dataset/constant/PageNumber'
import { VerticalAlign } from './dataset/enum/VerticalAlign'
import { TableBorder } from './dataset/enum/table/Table'
import { IFooter } from './interface/Footer'
import { defaultFooterOption } from './dataset/constant/Footer'
import { MaxHeightRatio } from './dataset/enum/Common'
export default class Editor {
@ -48,6 +51,10 @@ export default class Editor {
...defaultHeaderOption,
...options.header
}
const footerOptions: Required<IFooter> = {
...defaultFooterOption,
...options.footer
}
const pageNumberOptions: Required<IPageNumber> = {
...defaultPageNumberOption,
...options.pageNumber
@ -105,6 +112,7 @@ export default class Editor {
inactiveAlpha: 0.6,
...options,
header: headerOptions,
footer: footerOptions,
pageNumber: pageNumberOptions,
watermark: waterMarkOptions,
control: controlOptions,
@ -114,18 +122,20 @@ export default class Editor {
// 数据处理
let headerElementList: IElement[] = []
let mainElementList: IElement[] = []
let footerElementList: IElement[] = []
if (Array.isArray(data)) {
mainElementList = data
} else {
headerElementList = data.header || []
mainElementList = data.main
footerElementList = data.footer || []
}
formatElementList(headerElementList, {
editorOptions
})
formatElementList(mainElementList, {
editorOptions
})
[headerElementList, mainElementList, footerElementList]
.forEach(elementList => {
formatElementList(elementList, {
editorOptions
})
})
// 监听
this.listener = new Listener()
// 启动
@ -134,7 +144,8 @@ export default class Editor {
editorOptions,
{
header: headerElementList,
main: mainElementList
main: mainElementList,
footer: footerElementList
},
this.listener
)
@ -177,7 +188,8 @@ export {
KeyMap,
BlockType,
PaperDirection,
TableBorder
TableBorder,
MaxHeightRatio
}
// 对外类型

@ -3,6 +3,7 @@ import { EditorMode, PageMode, PaperDirection } from '../dataset/enum/Editor'
import { ICheckboxOption } from './Checkbox'
import { IControlOption } from './Control'
import { ICursorOption } from './Cursor'
import { IFooter } from './Footer'
import { IHeader } from './Header'
import { IMargin } from './Margin'
import { IPageNumber } from './PageNumber'
@ -49,6 +50,7 @@ export interface IEditorOption {
paperDirection?: PaperDirection;
inactiveAlpha?: number;
header?: IHeader;
footer?: IFooter;
pageNumber?: IPageNumber;
watermark?: IWatermark;
control?: IControlOption;

@ -0,0 +1,6 @@
import { MaxHeightRatio } from '../dataset/enum/Common'
export interface IFooter {
bottom?: number;
maxHeightRadio?: MaxHeightRatio;
}

@ -1,6 +1,6 @@
import { HeaderMaxHeightRatio } from '../dataset/enum/Header'
import { MaxHeightRatio } from '../dataset/enum/Common'
export interface IHeader {
top?: number;
maxHeightRadio?: HeaderMaxHeightRatio;
maxHeightRadio?: MaxHeightRatio;
}

@ -26,7 +26,11 @@ window.onload = function () {
value: '\n',
type: ElementType.SEPARATOR
}],
main: <IElement[]>data
main: <IElement[]>data,
footer: [{
value: 'canvas-editor',
size: 12
}]
},
options
)

Loading…
Cancel
Save