feat:add page zoom
This commit is contained in:
+5
-5
@@ -121,12 +121,12 @@
|
|||||||
<span>页面:<span class="page-no">1</span>/<span class="page-size">1</span></span>
|
<span>页面:<span class="page-no">1</span>/<span class="page-size">1</span></span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div class="page-scale-minus">
|
||||||
<i class="page-minus"></i>
|
<i></i>
|
||||||
</div>
|
</div>
|
||||||
<span>100%</span>
|
<span class="page-scale-percentage">100%</span>
|
||||||
<div>
|
<div class="page-scale-add">
|
||||||
<i class="page-add"></i>
|
<i></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 165 B After Width: | Height: | Size: 165 B |
|
Before Width: | Height: | Size: 148 B After Width: | Height: | Size: 148 B |
@@ -24,6 +24,8 @@ export class Command {
|
|||||||
private static image: Function
|
private static image: Function
|
||||||
private static search: Function
|
private static search: Function
|
||||||
private static print: Function
|
private static print: Function
|
||||||
|
private static pageScaleMinus: Function
|
||||||
|
private static pageScaleAdd: Function
|
||||||
|
|
||||||
constructor(adapt: CommandAdapt) {
|
constructor(adapt: CommandAdapt) {
|
||||||
Command.undo = adapt.undo.bind(adapt)
|
Command.undo = adapt.undo.bind(adapt)
|
||||||
@@ -46,6 +48,8 @@ export class Command {
|
|||||||
Command.image = adapt.image.bind(adapt)
|
Command.image = adapt.image.bind(adapt)
|
||||||
Command.search = adapt.search.bind(adapt)
|
Command.search = adapt.search.bind(adapt)
|
||||||
Command.print = adapt.print.bind(adapt)
|
Command.print = adapt.print.bind(adapt)
|
||||||
|
Command.pageScaleMinus = adapt.pageScaleMinus.bind(adapt)
|
||||||
|
Command.pageScaleAdd = adapt.pageScaleAdd.bind(adapt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 撤销、重做、格式刷、清除格式
|
// 撤销、重做、格式刷、清除格式
|
||||||
@@ -131,4 +135,13 @@ export class Command {
|
|||||||
return Command.print()
|
return Command.print()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 页面缩放
|
||||||
|
public executePageScaleMinus() {
|
||||||
|
return Command.pageScaleMinus()
|
||||||
|
}
|
||||||
|
|
||||||
|
public executePageScaleAdd() {
|
||||||
|
return Command.pageScaleAdd()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -262,4 +262,20 @@ export class CommandAdapt {
|
|||||||
return printImageBase64(this.draw.getDataURL(), width, height)
|
return printImageBase64(this.draw.getDataURL(), width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public pageScaleMinus() {
|
||||||
|
const { scale } = this.options
|
||||||
|
const nextScale = scale * 10 - 1
|
||||||
|
if (nextScale >= 5) {
|
||||||
|
this.draw.setPageScale(nextScale / 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public pageScaleAdd() {
|
||||||
|
const { scale } = this.options
|
||||||
|
const nextScale = scale * 10 + 1
|
||||||
|
if (nextScale <= 30) {
|
||||||
|
this.draw.setPageScale(nextScale / 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@ import { CursorAgent } from "./CursorAgent"
|
|||||||
|
|
||||||
export class Cursor {
|
export class Cursor {
|
||||||
|
|
||||||
|
private draw: Draw
|
||||||
private container: HTMLDivElement
|
private container: HTMLDivElement
|
||||||
private options: Required<IEditorOption>
|
private options: Required<IEditorOption>
|
||||||
private position: Position
|
private position: Position
|
||||||
@@ -14,6 +15,7 @@ export class Cursor {
|
|||||||
private cursorAgent: CursorAgent
|
private cursorAgent: CursorAgent
|
||||||
|
|
||||||
constructor(draw: Draw, canvasEvent: CanvasEvent) {
|
constructor(draw: Draw, canvasEvent: CanvasEvent) {
|
||||||
|
this.draw = draw
|
||||||
this.container = draw.getContainer()
|
this.container = draw.getContainer()
|
||||||
this.position = draw.getPosition()
|
this.position = draw.getPosition()
|
||||||
this.options = draw.getOptions()
|
this.options = draw.getOptions()
|
||||||
@@ -36,8 +38,10 @@ export class Cursor {
|
|||||||
const cursorPosition = this.position.getCursorPosition()
|
const cursorPosition = this.position.getCursorPosition()
|
||||||
if (!cursorPosition) return
|
if (!cursorPosition) return
|
||||||
// 设置光标代理
|
// 设置光标代理
|
||||||
|
const { scale } = this.options
|
||||||
|
const height = this.draw.getHeight()
|
||||||
|
const pageGap = this.draw.getPageGap()
|
||||||
const { metrics, coordinate: { leftTop, rightTop }, ascent, pageNo } = cursorPosition
|
const { metrics, coordinate: { leftTop, rightTop }, ascent, pageNo } = cursorPosition
|
||||||
const { height, pageGap } = this.options
|
|
||||||
const preY = pageNo * (height + pageGap)
|
const preY = pageNo * (height + pageGap)
|
||||||
// 增加1/4字体大小
|
// 增加1/4字体大小
|
||||||
const offsetHeight = metrics.height / 4
|
const offsetHeight = metrics.height / 4
|
||||||
@@ -52,7 +56,7 @@ export class Cursor {
|
|||||||
const cursorTop = (leftTop[1] + ascent) + descent - (cursorHeight - offsetHeight) + preY
|
const cursorTop = (leftTop[1] + ascent) + descent - (cursorHeight - offsetHeight) + preY
|
||||||
const curosrleft = rightTop[0]
|
const curosrleft = rightTop[0]
|
||||||
agentCursorDom.style.left = `${curosrleft}px`
|
agentCursorDom.style.left = `${curosrleft}px`
|
||||||
agentCursorDom.style.top = `${cursorTop + cursorHeight - CURSOR_AGENT_HEIGHT}px`
|
agentCursorDom.style.top = `${cursorTop + cursorHeight - CURSOR_AGENT_HEIGHT * scale}px`
|
||||||
// 模拟光标显示
|
// 模拟光标显示
|
||||||
this.cursorDom.style.left = `${curosrleft}px`
|
this.cursorDom.style.left = `${curosrleft}px`
|
||||||
this.cursorDom.style.top = `${cursorTop}px`
|
this.cursorDom.style.top = `${cursorTop}px`
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ export class Draw {
|
|||||||
private textParticle: TextParticle
|
private textParticle: TextParticle
|
||||||
private pageNumber: PageNumber
|
private pageNumber: PageNumber
|
||||||
|
|
||||||
private innerWidth: number
|
|
||||||
private rowList: IRow[]
|
private rowList: IRow[]
|
||||||
private painterStyle: IElementStyle | null
|
private painterStyle: IElementStyle | null
|
||||||
private searchMatchList: number[][] | null
|
private searchMatchList: number[][] | null
|
||||||
@@ -93,8 +92,6 @@ export class Draw {
|
|||||||
const globalEvent = new GlobalEvent(this, canvasEvent)
|
const globalEvent = new GlobalEvent(this, canvasEvent)
|
||||||
globalEvent.register()
|
globalEvent.register()
|
||||||
|
|
||||||
const { width, margins } = options
|
|
||||||
this.innerWidth = width - margins[1] - margins[3]
|
|
||||||
this.rowList = []
|
this.rowList = []
|
||||||
this.painterStyle = null
|
this.painterStyle = null
|
||||||
this.searchMatchList = null
|
this.searchMatchList = null
|
||||||
@@ -104,6 +101,40 @@ export class Draw {
|
|||||||
this.render({ isSetCursor: false })
|
this.render({ isSetCursor: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getWidth(): number {
|
||||||
|
return Math.floor(this.options.width * this.options.scale)
|
||||||
|
}
|
||||||
|
|
||||||
|
public getHeight(): number {
|
||||||
|
return Math.floor(this.options.height * this.options.scale)
|
||||||
|
}
|
||||||
|
|
||||||
|
public getInnerWidth(): number {
|
||||||
|
const width = this.getWidth()
|
||||||
|
const margins = this.getMargins()
|
||||||
|
return width - margins[1] - margins[3]
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMargins(): number[] {
|
||||||
|
return this.options.margins.map(m => m * this.options.scale)
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPageGap(): number {
|
||||||
|
return this.options.pageGap * this.options.scale
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPageNumberBottom(): number {
|
||||||
|
return this.options.pageNumberBottom * this.options.scale
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMarginIndicatorSize(): number {
|
||||||
|
return this.options.marginIndicatorSize * this.options.scale
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDefaultBasicRowMarginHeight(): number {
|
||||||
|
return this.options.defaultBasicRowMarginHeight * this.options.scale
|
||||||
|
}
|
||||||
|
|
||||||
public getContainer(): HTMLDivElement {
|
public getContainer(): HTMLDivElement {
|
||||||
return this.container
|
return this.container
|
||||||
}
|
}
|
||||||
@@ -222,9 +253,27 @@ export class Draw {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setPageScale(payload: number) {
|
||||||
|
this.options.scale = payload
|
||||||
|
const width = this.getWidth()
|
||||||
|
const height = this.getHeight()
|
||||||
|
this.container.style.width = `${width}px`
|
||||||
|
this.pageList.forEach(p => {
|
||||||
|
p.width = width
|
||||||
|
p.height = height
|
||||||
|
p.style.width = `${width}px`
|
||||||
|
p.style.height = `${height}px`
|
||||||
|
p.style.marginBottom = `${this.getPageGap()}px`
|
||||||
|
})
|
||||||
|
this.render({ isSubmitHistory: false, isSetCursor: false })
|
||||||
|
if (this.listener.pageScaleChange) {
|
||||||
|
this.listener.pageScaleChange(payload)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _createPageContainer(): HTMLDivElement {
|
private _createPageContainer(): HTMLDivElement {
|
||||||
// 容器宽度需跟随纸张宽度
|
// 容器宽度需跟随纸张宽度
|
||||||
this.container.style.width = `${this.options.width}px`
|
this.container.style.width = `${this.getWidth()}px`
|
||||||
const pageContainer = document.createElement('div')
|
const pageContainer = document.createElement('div')
|
||||||
pageContainer.classList.add('page-container')
|
pageContainer.classList.add('page-container')
|
||||||
this.container.append(pageContainer)
|
this.container.append(pageContainer)
|
||||||
@@ -232,16 +281,18 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _createPage(pageNo: number) {
|
private _createPage(pageNo: number) {
|
||||||
|
const width = this.getWidth()
|
||||||
|
const height = this.getHeight()
|
||||||
const canvas = document.createElement('canvas')
|
const canvas = document.createElement('canvas')
|
||||||
canvas.style.width = `${this.options.width}px`
|
canvas.style.width = `${width}px`
|
||||||
canvas.style.height = `${this.options.height}px`
|
canvas.style.height = `${height}px`
|
||||||
canvas.style.marginBottom = `${this.options.pageGap}px`
|
canvas.style.marginBottom = `${this.getPageGap()}px`
|
||||||
canvas.setAttribute('data-index', String(pageNo))
|
canvas.setAttribute('data-index', String(pageNo))
|
||||||
this.pageContainer.append(canvas)
|
this.pageContainer.append(canvas)
|
||||||
// 调整分辨率
|
// 调整分辨率
|
||||||
const dpr = window.devicePixelRatio
|
const dpr = window.devicePixelRatio
|
||||||
canvas.width = parseInt(canvas.style.width) * dpr
|
canvas.width = width * dpr
|
||||||
canvas.height = parseInt(canvas.style.height) * dpr
|
canvas.height = height * dpr
|
||||||
canvas.style.cursor = 'text'
|
canvas.style.cursor = 'text'
|
||||||
const ctx = canvas.getContext('2d')!
|
const ctx = canvas.getContext('2d')!
|
||||||
ctx.scale(dpr, dpr)
|
ctx.scale(dpr, dpr)
|
||||||
@@ -250,16 +301,17 @@ export class Draw {
|
|||||||
this.ctxList.push(ctx)
|
this.ctxList.push(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getFont(el: IElement): string {
|
private _getFont(el: IElement, scale: number = 1): string {
|
||||||
const { defaultSize, defaultFont } = this.options
|
const { defaultSize, defaultFont } = this.options
|
||||||
return `${el.italic ? 'italic ' : ''}${el.bold ? 'bold ' : ''}${el.size || defaultSize}px ${el.font || defaultFont}`
|
return `${el.italic ? 'italic ' : ''}${el.bold ? 'bold ' : ''}${(el.size || defaultSize) * scale}px ${el.font || defaultFont}`
|
||||||
}
|
}
|
||||||
|
|
||||||
private _computeRowList() {
|
private _computeRowList() {
|
||||||
const { defaultSize, defaultRowMargin, defaultBasicRowMarginHeight } = this.options
|
const { defaultSize, defaultRowMargin, scale } = this.options
|
||||||
|
const innerWidth = this.getInnerWidth()
|
||||||
|
const defaultBasicRowMarginHeight = this.getDefaultBasicRowMarginHeight()
|
||||||
const canvas = document.createElement('canvas')
|
const canvas = document.createElement('canvas')
|
||||||
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
|
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
|
||||||
const innerWidth = this.innerWidth
|
|
||||||
const rowList: IRow[] = []
|
const rowList: IRow[] = []
|
||||||
if (this.elementList.length) {
|
if (this.elementList.length) {
|
||||||
rowList.push({
|
rowList.push({
|
||||||
@@ -281,24 +333,30 @@ export class Draw {
|
|||||||
boundingBoxDescent: 0
|
boundingBoxDescent: 0
|
||||||
}
|
}
|
||||||
if (element.type === ElementType.IMAGE) {
|
if (element.type === ElementType.IMAGE) {
|
||||||
metrics.height = element.height!
|
const elementWidth = element.width! * scale
|
||||||
|
const elementHeight = element.height! * scale
|
||||||
// 图片超出尺寸后自适应
|
// 图片超出尺寸后自适应
|
||||||
if (curRow.width + element.width! > innerWidth) {
|
if (curRow.width + elementWidth > innerWidth) {
|
||||||
// 计算剩余大小
|
// 计算剩余大小
|
||||||
const surplusWidth = innerWidth - curRow.width
|
const surplusWidth = innerWidth - curRow.width
|
||||||
element.width = surplusWidth
|
element.width = surplusWidth
|
||||||
element.height = element.height! * surplusWidth / element.width
|
element.height = elementHeight * surplusWidth / elementWidth
|
||||||
}
|
metrics.width = element.width
|
||||||
metrics.width = element.width!
|
metrics.height = element.height
|
||||||
metrics.boundingBoxAscent = 0
|
metrics.boundingBoxDescent = element.height
|
||||||
metrics.boundingBoxDescent = element.height!
|
|
||||||
} else {
|
} else {
|
||||||
metrics.height = element.size || this.options.defaultSize
|
metrics.width = elementWidth
|
||||||
|
metrics.height = elementHeight
|
||||||
|
metrics.boundingBoxDescent = elementHeight
|
||||||
|
}
|
||||||
|
metrics.boundingBoxAscent = 0
|
||||||
|
} else {
|
||||||
|
metrics.height = (element.size || this.options.defaultSize) * scale
|
||||||
ctx.font = this._getFont(element)
|
ctx.font = this._getFont(element)
|
||||||
const fontMetrics = this.textParticle.measureText(ctx, element)
|
const fontMetrics = this.textParticle.measureText(ctx, element)
|
||||||
metrics.width = fontMetrics.width
|
metrics.width = fontMetrics.width * scale
|
||||||
metrics.boundingBoxAscent = element.value === ZERO ? defaultSize : fontMetrics.actualBoundingBoxAscent
|
metrics.boundingBoxAscent = (element.value === ZERO ? defaultSize : fontMetrics.actualBoundingBoxAscent) * scale
|
||||||
metrics.boundingBoxDescent = fontMetrics.actualBoundingBoxDescent
|
metrics.boundingBoxDescent = fontMetrics.actualBoundingBoxDescent * scale
|
||||||
}
|
}
|
||||||
const ascent = metrics.boundingBoxAscent + rowMargin
|
const ascent = metrics.boundingBoxAscent + rowMargin
|
||||||
const descent = metrics.boundingBoxDescent + rowMargin
|
const descent = metrics.boundingBoxDescent + rowMargin
|
||||||
@@ -306,7 +364,7 @@ export class Draw {
|
|||||||
const rowElement: IRowElement = {
|
const rowElement: IRowElement = {
|
||||||
...element,
|
...element,
|
||||||
metrics,
|
metrics,
|
||||||
style: ctx.font
|
style: this._getFont(element, scale)
|
||||||
}
|
}
|
||||||
// 超过限定宽度
|
// 超过限定宽度
|
||||||
if (curRow.width + metrics.width > innerWidth || (i !== 0 && element.value === ZERO)) {
|
if (curRow.width + metrics.width > innerWidth || (i !== 0 && element.value === ZERO)) {
|
||||||
@@ -322,7 +380,7 @@ export class Draw {
|
|||||||
if (curRow.height < height) {
|
if (curRow.height < height) {
|
||||||
curRow.height = height
|
curRow.height = height
|
||||||
if (element.type === ElementType.IMAGE) {
|
if (element.type === ElementType.IMAGE) {
|
||||||
curRow.ascent = element.height!
|
curRow.ascent = metrics.height
|
||||||
} else {
|
} else {
|
||||||
curRow.ascent = ascent
|
curRow.ascent = ascent
|
||||||
}
|
}
|
||||||
@@ -334,7 +392,9 @@ export class Draw {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _drawElement(positionList: IElementPosition[], rowList: IRow[], pageNo: number) {
|
private _drawElement(positionList: IElementPosition[], rowList: IRow[], pageNo: number) {
|
||||||
const { margins, width, height } = this.options
|
const width = this.getWidth()
|
||||||
|
const height = this.getHeight()
|
||||||
|
const margins = this.getMargins()
|
||||||
const ctx = this.ctxList[pageNo]
|
const ctx = this.ctxList[pageNo]
|
||||||
ctx.clearRect(0, 0, width, height)
|
ctx.clearRect(0, 0, width, height)
|
||||||
// 绘制背景
|
// 绘制背景
|
||||||
@@ -361,7 +421,7 @@ export class Draw {
|
|||||||
const element = curRow.elementList[j]
|
const element = curRow.elementList[j]
|
||||||
const metrics = element.metrics
|
const metrics = element.metrics
|
||||||
const offsetY = element.type === ElementType.IMAGE
|
const offsetY = element.type === ElementType.IMAGE
|
||||||
? curRow.ascent - element.height!
|
? curRow.ascent - metrics.height
|
||||||
: curRow.ascent
|
: curRow.ascent
|
||||||
const positionItem: IElementPosition = {
|
const positionItem: IElementPosition = {
|
||||||
pageNo,
|
pageNo,
|
||||||
@@ -430,6 +490,7 @@ export class Draw {
|
|||||||
isSetCursor = true,
|
isSetCursor = true,
|
||||||
isComputeRowList = true
|
isComputeRowList = true
|
||||||
} = payload || {}
|
} = payload || {}
|
||||||
|
const height = this.getHeight()
|
||||||
// 计算行信息
|
// 计算行信息
|
||||||
if (isComputeRowList) {
|
if (isComputeRowList) {
|
||||||
this._computeRowList()
|
this._computeRowList()
|
||||||
@@ -439,14 +500,14 @@ export class Draw {
|
|||||||
this.position.setPositionList([])
|
this.position.setPositionList([])
|
||||||
const positionList = this.position.getPositionList()
|
const positionList = this.position.getPositionList()
|
||||||
// 按页渲染
|
// 按页渲染
|
||||||
const { margins } = this.options
|
const margins = this.getMargins()
|
||||||
const marginHeight = margins[0] + margins[2]
|
const marginHeight = margins[0] + margins[2]
|
||||||
let pageHeight = marginHeight
|
let pageHeight = marginHeight
|
||||||
let pageNo = 0
|
let pageNo = 0
|
||||||
let pageRowList: IRow[][] = [[]]
|
let pageRowList: IRow[][] = [[]]
|
||||||
for (let i = 0; i < this.rowList.length; i++) {
|
for (let i = 0; i < this.rowList.length; i++) {
|
||||||
const row = this.rowList[i]
|
const row = this.rowList[i]
|
||||||
if (row.height + pageHeight > this.options.height) {
|
if (row.height + pageHeight > height) {
|
||||||
pageHeight = marginHeight + row.height
|
pageHeight = marginHeight + row.height
|
||||||
pageRowList.push([row])
|
pageRowList.push([row])
|
||||||
pageNo++
|
pageNo++
|
||||||
|
|||||||
@@ -3,15 +3,20 @@ import { Draw } from "../Draw"
|
|||||||
|
|
||||||
export class Margin {
|
export class Margin {
|
||||||
|
|
||||||
|
private draw: Draw
|
||||||
private options: Required<IEditorOption>
|
private options: Required<IEditorOption>
|
||||||
|
|
||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
|
this.draw = draw
|
||||||
this.options = draw.getOptions()
|
this.options = draw.getOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D) {
|
public render(ctx: CanvasRenderingContext2D) {
|
||||||
const { width, height } = this.options
|
const { marginIndicatorColor } = this.options
|
||||||
const { marginIndicatorColor, marginIndicatorSize, margins } = this.options
|
const width = this.draw.getWidth()
|
||||||
|
const height = this.draw.getHeight()
|
||||||
|
const margins = this.draw.getMargins()
|
||||||
|
const marginIndicatorSize = this.draw.getMarginIndicatorSize()
|
||||||
ctx.save()
|
ctx.save()
|
||||||
ctx.strokeStyle = marginIndicatorColor
|
ctx.strokeStyle = marginIndicatorColor
|
||||||
ctx.beginPath()
|
ctx.beginPath()
|
||||||
|
|||||||
@@ -3,17 +3,22 @@ import { Draw } from "../Draw"
|
|||||||
|
|
||||||
export class PageNumber {
|
export class PageNumber {
|
||||||
|
|
||||||
|
private draw: Draw
|
||||||
private options: Required<IEditorOption>
|
private options: Required<IEditorOption>
|
||||||
|
|
||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
|
this.draw = draw
|
||||||
this.options = draw.getOptions()
|
this.options = draw.getOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D, pageNo: number) {
|
public render(ctx: CanvasRenderingContext2D, pageNo: number) {
|
||||||
const { pageNumberBottom, width, height } = this.options
|
const { pageNumberSize, pageNumberFont, scale } = this.options
|
||||||
|
const width = this.draw.getWidth()
|
||||||
|
const height = this.draw.getHeight()
|
||||||
|
const pageNumberBottom = this.draw.getPageNumberBottom()
|
||||||
ctx.save()
|
ctx.save()
|
||||||
ctx.fillStyle = '#00000'
|
ctx.fillStyle = '#00000'
|
||||||
ctx.font = '12px'
|
ctx.font = `${pageNumberSize * scale}px ${pageNumberFont}`
|
||||||
ctx.fillText(`${pageNo + 1}`, width / 2, height - pageNumberBottom)
|
ctx.fillText(`${pageNo + 1}`, width / 2, height - pageNumberBottom)
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,9 @@ export class ImageParticle {
|
|||||||
private _handleMousedown(evt: MouseEvent) {
|
private _handleMousedown(evt: MouseEvent) {
|
||||||
this.canvas = this.draw.getPage()
|
this.canvas = this.draw.getPage()
|
||||||
if (!this.curPosition || !this.curElement) return
|
if (!this.curPosition || !this.curElement) return
|
||||||
const { height, pageGap } = this.options
|
const { scale } = this.options
|
||||||
|
const height = this.draw.getHeight()
|
||||||
|
const pageGap = this.draw.getPageGap()
|
||||||
this.mousedownX = evt.x
|
this.mousedownX = evt.x
|
||||||
this.mousedownY = evt.y
|
this.mousedownY = evt.y
|
||||||
const target = evt.target as HTMLDivElement
|
const target = evt.target as HTMLDivElement
|
||||||
@@ -88,8 +90,8 @@ export class ImageParticle {
|
|||||||
const prePageHeight = this.draw.getPageNo() * (height + pageGap)
|
const prePageHeight = this.draw.getPageNo() * (height + pageGap)
|
||||||
this.resizerImageContainer.style.left = `${left}px`
|
this.resizerImageContainer.style.left = `${left}px`
|
||||||
this.resizerImageContainer.style.top = `${top + prePageHeight}px`
|
this.resizerImageContainer.style.top = `${top + prePageHeight}px`
|
||||||
this.resizerImage.style.width = `${this.curElement.width}px`
|
this.resizerImage.style.width = `${this.curElement.width! * scale}px`
|
||||||
this.resizerImage.style.height = `${this.curElement.height}px`
|
this.resizerImage.style.height = `${this.curElement.height! * scale}px`
|
||||||
// 追加全局事件
|
// 追加全局事件
|
||||||
const mousemoveFn = this._mousemove.bind(this)
|
const mousemoveFn = this._mousemove.bind(this)
|
||||||
document.addEventListener('mousemove', mousemoveFn)
|
document.addEventListener('mousemove', mousemoveFn)
|
||||||
@@ -114,6 +116,7 @@ export class ImageParticle {
|
|||||||
|
|
||||||
private _mousemove(evt: MouseEvent) {
|
private _mousemove(evt: MouseEvent) {
|
||||||
if (!this.curElement) return
|
if (!this.curElement) return
|
||||||
|
const { scale } = this.options
|
||||||
let dx = 0
|
let dx = 0
|
||||||
let dy = 0
|
let dy = 0
|
||||||
switch (this.curHandleIndex) {
|
switch (this.curHandleIndex) {
|
||||||
@@ -148,8 +151,8 @@ export class ImageParticle {
|
|||||||
}
|
}
|
||||||
this.width = this.curElement.width! + dx
|
this.width = this.curElement.width! + dx
|
||||||
this.height = this.curElement.height! + dy
|
this.height = this.curElement.height! + dy
|
||||||
this.resizerImage.style.width = `${this.width}px`
|
this.resizerImage.style.width = `${this.width * scale}px`
|
||||||
this.resizerImage.style.height = `${this.height}px`
|
this.resizerImage.style.height = `${this.height * scale}px`
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,36 +161,39 @@ export class ImageParticle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public drawResizer(element: IElement, position: IElementPosition) {
|
public drawResizer(element: IElement, position: IElementPosition) {
|
||||||
|
const { scale } = this.options
|
||||||
const { coordinate: { leftTop: [left, top] } } = position
|
const { coordinate: { leftTop: [left, top] } } = position
|
||||||
const width = element.width!
|
const elementWidth = element.width! * scale
|
||||||
const height = element.height!
|
const elementHeight = element.height! * scale
|
||||||
|
const height = this.draw.getHeight()
|
||||||
|
const pageGap = this.draw.getPageGap()
|
||||||
const handleSize = this.options.resizerSize
|
const handleSize = this.options.resizerSize
|
||||||
const preY = this.draw.getPageNo() * (this.options.height + this.options.pageGap)
|
const preY = this.draw.getPageNo() * (height + pageGap)
|
||||||
// 边框
|
// 边框
|
||||||
this.resizerSelection.style.left = `${left}px`
|
this.resizerSelection.style.left = `${left}px`
|
||||||
this.resizerSelection.style.top = `${top + preY}px`
|
this.resizerSelection.style.top = `${top + preY}px`
|
||||||
this.resizerSelection.style.width = `${element.width}px`
|
this.resizerSelection.style.width = `${elementWidth}px`
|
||||||
this.resizerSelection.style.height = `${element.height}px`
|
this.resizerSelection.style.height = `${elementHeight}px`
|
||||||
// handle
|
// handle
|
||||||
for (let i = 0; i < 8; i++) {
|
for (let i = 0; i < 8; i++) {
|
||||||
const left = i === 0 || i === 6 || i === 7
|
const left = i === 0 || i === 6 || i === 7
|
||||||
? -handleSize
|
? -handleSize
|
||||||
: i === 1 || i === 5
|
: i === 1 || i === 5
|
||||||
? width / 2
|
? elementWidth / 2
|
||||||
: width - handleSize
|
: elementWidth - handleSize
|
||||||
const top = i === 0 || i === 1 || i === 2
|
const top = i === 0 || i === 1 || i === 2
|
||||||
? -handleSize
|
? -handleSize
|
||||||
: i === 3 || i === 7
|
: i === 3 || i === 7
|
||||||
? height / 2 - handleSize
|
? elementHeight / 2 - handleSize
|
||||||
: height - handleSize
|
: elementHeight - handleSize
|
||||||
this.resizerHandleList[i].style.left = `${left}px`
|
this.resizerHandleList[i].style.left = `${left}px`
|
||||||
this.resizerHandleList[i].style.top = `${top}px`
|
this.resizerHandleList[i].style.top = `${top}px`
|
||||||
}
|
}
|
||||||
this.resizerSelection.style.display = 'block'
|
this.resizerSelection.style.display = 'block'
|
||||||
this.curElement = element
|
this.curElement = element
|
||||||
this.curPosition = position
|
this.curPosition = position
|
||||||
this.width = this.curElement.width!
|
this.width = this.curElement.width! * scale
|
||||||
this.height = this.curElement.height!
|
this.height = this.curElement.height! * scale
|
||||||
}
|
}
|
||||||
|
|
||||||
public clearResizer() {
|
public clearResizer() {
|
||||||
@@ -195,8 +201,9 @@ export class ImageParticle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D, element: IElement, x: number, y: number) {
|
public render(ctx: CanvasRenderingContext2D, element: IElement, x: number, y: number) {
|
||||||
const width = element.width!
|
const { scale } = this.options
|
||||||
const height = element.height!
|
const width = element.width! * scale
|
||||||
|
const height = element.height! * scale
|
||||||
if (this.imageCache.has(element.id!)) {
|
if (this.imageCache.has(element.id!)) {
|
||||||
const img = this.imageCache.get(element.id!)!
|
const img = this.imageCache.get(element.id!)!
|
||||||
ctx.drawImage(img, x, y, width, height)
|
ctx.drawImage(img, x, y, width, height)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
IIntersectionPageNoChange,
|
IIntersectionPageNoChange,
|
||||||
|
IPageScaleChange,
|
||||||
IPageSizeChange,
|
IPageSizeChange,
|
||||||
IRangeStyleChange,
|
IRangeStyleChange,
|
||||||
IVisiblePageNoListChange
|
IVisiblePageNoListChange
|
||||||
@@ -11,12 +12,14 @@ export class Listener {
|
|||||||
public visiblePageNoListChange: IVisiblePageNoListChange | null
|
public visiblePageNoListChange: IVisiblePageNoListChange | null
|
||||||
public intersectionPageNoChange: IIntersectionPageNoChange | null
|
public intersectionPageNoChange: IIntersectionPageNoChange | null
|
||||||
public pageSizeChange: IPageSizeChange | null
|
public pageSizeChange: IPageSizeChange | null
|
||||||
|
public pageScaleChange: IPageScaleChange | null
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.rangeStyleChange = null
|
this.rangeStyleChange = null
|
||||||
this.visiblePageNoListChange = null
|
this.visiblePageNoListChange = null
|
||||||
this.intersectionPageNoChange = null
|
this.intersectionPageNoChange = null
|
||||||
this.pageSizeChange = null
|
this.pageSizeChange = null
|
||||||
|
this.pageScaleChange = null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -24,8 +24,11 @@ export default class Editor {
|
|||||||
defaultBasicRowMarginHeight: 8,
|
defaultBasicRowMarginHeight: 8,
|
||||||
width: 794,
|
width: 794,
|
||||||
height: 1123,
|
height: 1123,
|
||||||
|
scale: 1,
|
||||||
pageGap: 20,
|
pageGap: 20,
|
||||||
pageNumberBottom: 60,
|
pageNumberBottom: 60,
|
||||||
|
pageNumberSize: 12,
|
||||||
|
pageNumberFont: 'Yahei',
|
||||||
underlineColor: '#000000',
|
underlineColor: '#000000',
|
||||||
strikeoutColor: '#FF0000',
|
strikeoutColor: '#FF0000',
|
||||||
rangeAlpha: 0.6,
|
rangeAlpha: 0.6,
|
||||||
|
|||||||
@@ -6,8 +6,11 @@ export interface IEditorOption {
|
|||||||
defaultRowMargin?: number;
|
defaultRowMargin?: number;
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number;
|
height?: number;
|
||||||
|
scale?: number;
|
||||||
pageGap?: number;
|
pageGap?: number;
|
||||||
pageNumberBottom?: number;
|
pageNumberBottom?: number;
|
||||||
|
pageNumberSize?: number;
|
||||||
|
pageNumberFont?: string;
|
||||||
underlineColor?: string;
|
underlineColor?: string;
|
||||||
strikeoutColor?: string;
|
strikeoutColor?: string;
|
||||||
rangeColor?: string;
|
rangeColor?: string;
|
||||||
|
|||||||
@@ -22,3 +22,5 @@ export type IVisiblePageNoListChange = (payload: number[]) => void
|
|||||||
export type IIntersectionPageNoChange = (payload: number) => void
|
export type IIntersectionPageNoChange = (payload: number) => void
|
||||||
|
|
||||||
export type IPageSizeChange = (payload: number) => void
|
export type IPageSizeChange = (payload: number) => void
|
||||||
|
|
||||||
|
export type IPageScaleChange = (payload: number) => void
|
||||||
|
|||||||
+12
@@ -231,6 +231,14 @@ window.onload = function () {
|
|||||||
console.log('print')
|
console.log('print')
|
||||||
instance.command.executePrint()
|
instance.command.executePrint()
|
||||||
}
|
}
|
||||||
|
document.querySelector<HTMLDivElement>('.page-scale-minus')!.onclick = function () {
|
||||||
|
console.log('page-scale-minus')
|
||||||
|
instance.command.executePageScaleMinus()
|
||||||
|
}
|
||||||
|
document.querySelector<HTMLDivElement>('.page-scale-add')!.onclick = function () {
|
||||||
|
console.log('page-scale-add')
|
||||||
|
instance.command.executePageScaleAdd()
|
||||||
|
}
|
||||||
|
|
||||||
// 内部事件监听
|
// 内部事件监听
|
||||||
instance.listener.rangeStyleChange = function (payload) {
|
instance.listener.rangeStyleChange = function (payload) {
|
||||||
@@ -295,4 +303,8 @@ window.onload = function () {
|
|||||||
document.querySelector<HTMLSpanElement>('.page-no')!.innerText = `${payload + 1}`
|
document.querySelector<HTMLSpanElement>('.page-no')!.innerText = `${payload + 1}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instance.listener.pageScaleChange = function (payload) {
|
||||||
|
document.querySelector<HTMLSpanElement>('.page-scale-percentage')!.innerText = `${Math.floor(payload * 100)}%`
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+8
-5
@@ -395,11 +395,14 @@ ul {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer>div:last-child .page-minus {
|
.footer .page-scale-minus i {
|
||||||
background-image: url('./assets/images/page-minus.svg');
|
background-image: url('./assets/images/page-scale-minus.svg');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer>div:last-child .page-add {
|
.footer .page-scale-add i {
|
||||||
background-image: url('./assets/images/page-add.svg');
|
background-image: url('./assets/images/page-scale-add.svg');
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer .page-scale-percentage {
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user