parent
8202c1c67b
commit
c2330a8c11
|
After Width: | Height: | Size: 398 B |
@ -0,0 +1,97 @@
|
|||||||
|
import { ZERO } from '../../../dataset/constant/Common'
|
||||||
|
import { ulStyleMapping } from '../../../dataset/constant/List'
|
||||||
|
import { KeyMap } from '../../../dataset/enum/KeyMap'
|
||||||
|
import { ListStyle, ListType, UlStyle } from '../../../dataset/enum/List'
|
||||||
|
import { DeepRequired } from '../../../interface/Common'
|
||||||
|
import { IEditorOption } from '../../../interface/Editor'
|
||||||
|
import { IElement, IElementPosition } from '../../../interface/Element'
|
||||||
|
import { IRow } from '../../../interface/Row'
|
||||||
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
|
export class ListParticle {
|
||||||
|
|
||||||
|
private options: DeepRequired<IEditorOption>
|
||||||
|
|
||||||
|
// 非递增样式直接返回默认值
|
||||||
|
private readonly UN_COUNT_STYLE_WIDTH = 20
|
||||||
|
private readonly MEASURE_BASE_TEXT = '0'
|
||||||
|
private readonly LIST_GAP = 10
|
||||||
|
|
||||||
|
constructor(draw: Draw) {
|
||||||
|
this.options = draw.getOptions()
|
||||||
|
}
|
||||||
|
|
||||||
|
public computeListStyle(ctx: CanvasRenderingContext2D, elementList: IElement[]): Map<string, number> {
|
||||||
|
const listStyleMap = new Map<string, number>()
|
||||||
|
let start = 0
|
||||||
|
let curListId = elementList[start].listId
|
||||||
|
let curElementList: IElement[] = []
|
||||||
|
const elementLength = elementList.length
|
||||||
|
while (start < elementLength) {
|
||||||
|
const curElement = elementList[start]
|
||||||
|
if (curListId && curListId === curElement.listId) {
|
||||||
|
curElementList.push(curElement)
|
||||||
|
} else {
|
||||||
|
if (curElement.listId && curElement.listId !== curListId) {
|
||||||
|
// 列表结束
|
||||||
|
if (curElementList.length) {
|
||||||
|
const width = this.getListStyleWidth(ctx, curElementList)
|
||||||
|
listStyleMap.set(curListId!, width)
|
||||||
|
}
|
||||||
|
curListId = curElement.listId
|
||||||
|
curElementList = curListId ? [curElement] : []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
start++
|
||||||
|
}
|
||||||
|
if (curElementList.length) {
|
||||||
|
const width = this.getListStyleWidth(ctx, curElementList)
|
||||||
|
listStyleMap.set(curListId!, width)
|
||||||
|
}
|
||||||
|
return listStyleMap
|
||||||
|
}
|
||||||
|
|
||||||
|
public getListStyleWidth(ctx: CanvasRenderingContext2D, listElementList: IElement[]): number {
|
||||||
|
const startElement = listElementList[0]
|
||||||
|
// 非递增样式返回固定值
|
||||||
|
if (startElement.listStyle && startElement.listStyle !== ListStyle.DECIMAL) {
|
||||||
|
return this.UN_COUNT_STYLE_WIDTH
|
||||||
|
}
|
||||||
|
// 计算列表数量
|
||||||
|
const count = listElementList.reduce((pre, cur) => {
|
||||||
|
if (cur.value === ZERO) {
|
||||||
|
pre += 1
|
||||||
|
}
|
||||||
|
return pre
|
||||||
|
}, 0)
|
||||||
|
if (!count) return 0
|
||||||
|
// 以递增样式最大宽度为准
|
||||||
|
const text = `${this.MEASURE_BASE_TEXT.repeat(String(count).length)}${KeyMap.PERIOD}`
|
||||||
|
const textMetrics = ctx.measureText(text)
|
||||||
|
return Math.ceil(textMetrics.width + this.LIST_GAP)
|
||||||
|
}
|
||||||
|
|
||||||
|
public drawListStyle(ctx: CanvasRenderingContext2D, row: IRow, position: IElementPosition) {
|
||||||
|
const { elementList, offsetX, listIndex, ascent } = row
|
||||||
|
const startElement = elementList[0]
|
||||||
|
if (startElement.value !== ZERO) return
|
||||||
|
let text = ''
|
||||||
|
if (startElement.listType === ListType.UL) {
|
||||||
|
if (startElement.listStyle) {
|
||||||
|
text = ulStyleMapping[<UlStyle><unknown>startElement.listStyle]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text = `${listIndex! + 1}${KeyMap.PERIOD}`
|
||||||
|
}
|
||||||
|
if (!text) return
|
||||||
|
const { coordinate: { leftTop: [startX, startY] } } = position
|
||||||
|
const x = startX - offsetX!
|
||||||
|
const y = startY + ascent
|
||||||
|
const { defaultFont, defaultSize, scale } = this.options
|
||||||
|
ctx.save()
|
||||||
|
ctx.font = `${defaultSize * scale}px ${defaultFont}`
|
||||||
|
ctx.fillText(text, x, y)
|
||||||
|
ctx.restore()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
import { UlStyle } from '../enum/List'
|
||||||
|
|
||||||
|
export const ulStyleMapping: Record<UlStyle, string> = {
|
||||||
|
[UlStyle.DISC]: '•',
|
||||||
|
[UlStyle.CIRCLE]: '◦',
|
||||||
|
[UlStyle.SQUARE]: '▫︎'
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
export enum ListType {
|
||||||
|
UL = 'ul',
|
||||||
|
OL = 'ol'
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum UlStyle {
|
||||||
|
DISC = 'disc', // 实心圆点
|
||||||
|
CIRCLE = 'circle', // 空心圆点
|
||||||
|
SQUARE = 'square', // 实心方块
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum OlStyle {
|
||||||
|
DECIMAL = 'decimal' // 阿拉伯数字
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ListStyle {
|
||||||
|
DISC = UlStyle.DISC,
|
||||||
|
CIRCLE = UlStyle.CIRCLE,
|
||||||
|
SQUARE = UlStyle.SQUARE,
|
||||||
|
DECIMAL = OlStyle.DECIMAL
|
||||||
|
}
|
||||||
Loading…
Reference in new issue