Merge pull request #151 from zhoujingfu/catalogue
feat: font size setting api
This commit is contained in:
@@ -37,6 +37,32 @@ describe('菜单-文本处理', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('字号设置', () => {
|
||||||
|
cy.getEditor().then((editor: Editor) => {
|
||||||
|
editor.command.executeSelectAll()
|
||||||
|
|
||||||
|
editor.command.executeBackspace()
|
||||||
|
|
||||||
|
editor.command.executeInsertElementList([{
|
||||||
|
value: text
|
||||||
|
}])
|
||||||
|
|
||||||
|
editor.command.executeSetRange(0, textLength)
|
||||||
|
|
||||||
|
cy.get('.menu-item__size').as('size').click()
|
||||||
|
|
||||||
|
cy.get('@size')
|
||||||
|
.find('li')
|
||||||
|
.eq(0)
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
const data = editor.command.getValue().data.main
|
||||||
|
|
||||||
|
expect(data[0].size).to.eq(56)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
it('字体增大', () => {
|
it('字体增大', () => {
|
||||||
cy.getEditor().then((editor: Editor) => {
|
cy.getEditor().then((editor: Editor) => {
|
||||||
editor.command.executeSelectAll()
|
editor.command.executeSelectAll()
|
||||||
|
|||||||
@@ -113,6 +113,14 @@ instance.command.executeFormat()
|
|||||||
instance.command.executeFont(font: string)
|
instance.command.executeFont(font: string)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## executeSize
|
||||||
|
功能:设置字号
|
||||||
|
|
||||||
|
用法:
|
||||||
|
```javascript
|
||||||
|
instance.command.executeSize(size: number)
|
||||||
|
```
|
||||||
|
|
||||||
## executeSizeAdd
|
## executeSizeAdd
|
||||||
功能:增大字号
|
功能:增大字号
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ interface IEditorOption {
|
|||||||
defaultType?: string; // 默认元素类型。默认:TEXT
|
defaultType?: string; // 默认元素类型。默认:TEXT
|
||||||
defaultFont?: string; // 默认字体。默认:Yahei
|
defaultFont?: string; // 默认字体。默认:Yahei
|
||||||
defaultSize?: number; // 默认字号。默认:16
|
defaultSize?: number; // 默认字号。默认:16
|
||||||
|
minSize?: number; // 最小字号。默认:5
|
||||||
|
maxSize?: number; // 最大字号。默认:72
|
||||||
defaultBasicRowMarginHeight?: number; // 默认行高。默认:8
|
defaultBasicRowMarginHeight?: number; // 默认行高。默认:8
|
||||||
defaultRowMargin?: number; // 默认行间距。默认:1
|
defaultRowMargin?: number; // 默认行间距。默认:1
|
||||||
defaultTabWidth?: number; // 默认tab宽度。默认:32
|
defaultTabWidth?: number; // 默认tab宽度。默认:32
|
||||||
|
|||||||
+23
@@ -51,6 +51,29 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="menu-item__size">
|
||||||
|
<span class="select" title="字体">小四</span>
|
||||||
|
<div class="options">
|
||||||
|
<ul>
|
||||||
|
<li data-size="56">初号</li>
|
||||||
|
<li data-size="48">小初</li>
|
||||||
|
<li data-size="34">一号</li>
|
||||||
|
<li data-size="32">小一</li>
|
||||||
|
<li data-size="29">二号</li>
|
||||||
|
<li data-size="24">小二</li>
|
||||||
|
<li data-size="21">三号</li>
|
||||||
|
<li data-size="20">小三</li>
|
||||||
|
<li data-size="18">四号</li>
|
||||||
|
<li data-size="16">小四</li>
|
||||||
|
<li data-size="14">五号</li>
|
||||||
|
<li data-size="12">小五</li>
|
||||||
|
<li data-size="10">六号</li>
|
||||||
|
<li data-size="8">小六</li>
|
||||||
|
<li data-size="7">七号</li>
|
||||||
|
<li data-size="6">八号</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="menu-item__size-add">
|
<div class="menu-item__size-add">
|
||||||
<i></i>
|
<i></i>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export class Command {
|
|||||||
private static applyPainterStyle: CommandAdapt['applyPainterStyle']
|
private static applyPainterStyle: CommandAdapt['applyPainterStyle']
|
||||||
private static format: CommandAdapt['format']
|
private static format: CommandAdapt['format']
|
||||||
private static font: CommandAdapt['font']
|
private static font: CommandAdapt['font']
|
||||||
|
private static size: CommandAdapt['size']
|
||||||
private static sizeAdd: CommandAdapt['sizeAdd']
|
private static sizeAdd: CommandAdapt['sizeAdd']
|
||||||
private static sizeMinus: CommandAdapt['sizeMinus']
|
private static sizeMinus: CommandAdapt['sizeMinus']
|
||||||
private static bold: CommandAdapt['bold']
|
private static bold: CommandAdapt['bold']
|
||||||
@@ -96,6 +97,7 @@ export class Command {
|
|||||||
Command.applyPainterStyle = adapt.applyPainterStyle.bind(adapt)
|
Command.applyPainterStyle = adapt.applyPainterStyle.bind(adapt)
|
||||||
Command.format = adapt.format.bind(adapt)
|
Command.format = adapt.format.bind(adapt)
|
||||||
Command.font = adapt.font.bind(adapt)
|
Command.font = adapt.font.bind(adapt)
|
||||||
|
Command.size = adapt.size.bind(adapt)
|
||||||
Command.sizeAdd = adapt.sizeAdd.bind(adapt)
|
Command.sizeAdd = adapt.sizeAdd.bind(adapt)
|
||||||
Command.sizeMinus = adapt.sizeMinus.bind(adapt)
|
Command.sizeMinus = adapt.sizeMinus.bind(adapt)
|
||||||
Command.bold = adapt.bold.bind(adapt)
|
Command.bold = adapt.bold.bind(adapt)
|
||||||
@@ -207,11 +209,15 @@ export class Command {
|
|||||||
return Command.format()
|
return Command.format()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 字体、字体变大、字体变小、加粗、斜体、下划线、删除线、字体颜色、背景色
|
// 字体、字体大小、字体变大、字体变小、加粗、斜体、下划线、删除线、字体颜色、背景色
|
||||||
public executeFont(payload: string) {
|
public executeFont(payload: string) {
|
||||||
return Command.font(payload)
|
return Command.font(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public executeSize(payload: number) {
|
||||||
|
return Command.size(payload)
|
||||||
|
}
|
||||||
|
|
||||||
public executeSizeAdd() {
|
public executeSizeAdd() {
|
||||||
return Command.sizeAdd()
|
return Command.sizeAdd()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,41 +186,71 @@ export class CommandAdapt {
|
|||||||
this.draw.render({ isSetCursor: false })
|
this.draw.render({ isSetCursor: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public size(payload: number) {
|
||||||
|
const { minSize, maxSize, defaultSize } = this.options
|
||||||
|
if (payload < minSize || payload > maxSize) return
|
||||||
|
const isReadonly = this.draw.isReadonly()
|
||||||
|
if (isReadonly) return
|
||||||
|
const selection = this.range.getTextLikeSelection()
|
||||||
|
if (!selection || !selection.length) return
|
||||||
|
let isExistUpdate = false
|
||||||
|
selection.forEach(el => {
|
||||||
|
if ((!el.size && payload === defaultSize) || (el.size && el.size === payload)) return
|
||||||
|
el.size = payload
|
||||||
|
isExistUpdate = true
|
||||||
|
})
|
||||||
|
if (isExistUpdate) {
|
||||||
|
this.draw.render({ isSetCursor: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public sizeAdd() {
|
public sizeAdd() {
|
||||||
const isReadonly = this.draw.isReadonly()
|
const isReadonly = this.draw.isReadonly()
|
||||||
if (isReadonly) return
|
if (isReadonly) return
|
||||||
const selection = this.range.getSelection()
|
const selection = this.range.getTextLikeSelection()
|
||||||
if (!selection) return
|
if (!selection || !selection.length) return
|
||||||
const lessThanMaxSizeIndex = selection.findIndex(s => !s.size || s.size + 2 <= 72)
|
const { defaultSize, maxSize } = this.options
|
||||||
const { defaultSize } = this.options
|
let isExistUpdate = false
|
||||||
if (!~lessThanMaxSizeIndex) return
|
|
||||||
selection.forEach(el => {
|
selection.forEach(el => {
|
||||||
if (!el.size) {
|
if (!el.size) {
|
||||||
el.size = defaultSize
|
el.size = defaultSize
|
||||||
}
|
}
|
||||||
if (el.size + 2 > 72) return
|
if (el.size >= maxSize) return
|
||||||
|
if (el.size + 2 > maxSize) {
|
||||||
|
el.size = maxSize
|
||||||
|
} else {
|
||||||
el.size += 2
|
el.size += 2
|
||||||
|
}
|
||||||
|
isExistUpdate = true
|
||||||
})
|
})
|
||||||
|
if (isExistUpdate) {
|
||||||
this.draw.render({ isSetCursor: false })
|
this.draw.render({ isSetCursor: false })
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public sizeMinus() {
|
public sizeMinus() {
|
||||||
const isReadonly = this.draw.isReadonly()
|
const isReadonly = this.draw.isReadonly()
|
||||||
if (isReadonly) return
|
if (isReadonly) return
|
||||||
const selection = this.range.getSelection()
|
const selection = this.range.getTextLikeSelection()
|
||||||
if (!selection) return
|
if (!selection || !selection.length) return
|
||||||
const greaterThanMaxSizeIndex = selection.findIndex(s => !s.size || s.size - 2 >= 8)
|
const { defaultSize, minSize } = this.options
|
||||||
if (!~greaterThanMaxSizeIndex) return
|
let isExistUpdate = false
|
||||||
const { defaultSize } = this.options
|
|
||||||
selection.forEach(el => {
|
selection.forEach(el => {
|
||||||
if (!el.size) {
|
if (!el.size) {
|
||||||
el.size = defaultSize
|
el.size = defaultSize
|
||||||
}
|
}
|
||||||
if (el.size - 2 < 8) return
|
if (el.size <= minSize) return
|
||||||
|
if (el.size - 2 < minSize) {
|
||||||
|
el.size = minSize
|
||||||
|
} else {
|
||||||
el.size -= 2
|
el.size -= 2
|
||||||
|
}
|
||||||
|
isExistUpdate = true
|
||||||
})
|
})
|
||||||
|
if (isExistUpdate) {
|
||||||
this.draw.render({ isSetCursor: false })
|
this.draw.render({ isSetCursor: false })
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bold() {
|
public bold() {
|
||||||
const isReadonly = this.draw.isReadonly()
|
const isReadonly = this.draw.isReadonly()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ElementType } from '../..'
|
import { ElementType } from '../..'
|
||||||
import { ZERO } from '../../dataset/constant/Common'
|
import { ZERO } from '../../dataset/constant/Common'
|
||||||
|
import { TEXTLIKE_ELEMENT_TYPE } from '../../dataset/constant/Element'
|
||||||
import { ControlComponent } from '../../dataset/enum/Control'
|
import { ControlComponent } from '../../dataset/enum/Control'
|
||||||
import { IEditorOption } from '../../interface/Editor'
|
import { IEditorOption } from '../../interface/Editor'
|
||||||
import { IElement } from '../../interface/Element'
|
import { IElement } from '../../interface/Element'
|
||||||
@@ -45,6 +46,12 @@ export class RangeManager {
|
|||||||
return elementList.slice(startIndex + 1, endIndex + 1)
|
return elementList.slice(startIndex + 1, endIndex + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getTextLikeSelection(): IElement[] | null {
|
||||||
|
const selection = this.getSelection()
|
||||||
|
if (!selection) return null
|
||||||
|
return selection.filter(s => !s.type || TEXTLIKE_ELEMENT_TYPE.includes(s.type))
|
||||||
|
}
|
||||||
|
|
||||||
// 获取光标所选位置行信息
|
// 获取光标所选位置行信息
|
||||||
public getRangeRow(): RangeRowMap | null {
|
public getRangeRow(): RangeRowMap | null {
|
||||||
const { startIndex, endIndex } = this.range
|
const { startIndex, endIndex } = this.range
|
||||||
@@ -135,6 +142,7 @@ export class RangeManager {
|
|||||||
const type = curElement.type || ElementType.TEXT
|
const type = curElement.type || ElementType.TEXT
|
||||||
// 富文本
|
// 富文本
|
||||||
const font = curElement.font || this.options.defaultFont
|
const font = curElement.font || this.options.defaultFont
|
||||||
|
const size = curElement.size || this.options.defaultSize
|
||||||
const bold = !~curElementList.findIndex(el => !el.bold)
|
const bold = !~curElementList.findIndex(el => !el.bold)
|
||||||
const italic = !~curElementList.findIndex(el => !el.italic)
|
const italic = !~curElementList.findIndex(el => !el.italic)
|
||||||
const underline = !~curElementList.findIndex(el => !el.underline)
|
const underline = !~curElementList.findIndex(el => !el.underline)
|
||||||
@@ -154,6 +162,7 @@ export class RangeManager {
|
|||||||
redo,
|
redo,
|
||||||
painter,
|
painter,
|
||||||
font,
|
font,
|
||||||
|
size,
|
||||||
bold,
|
bold,
|
||||||
italic,
|
italic,
|
||||||
underline,
|
underline,
|
||||||
@@ -169,6 +178,7 @@ export class RangeManager {
|
|||||||
public recoveryRangeStyle() {
|
public recoveryRangeStyle() {
|
||||||
if (!this.listener.rangeStyleChange) return
|
if (!this.listener.rangeStyleChange) return
|
||||||
const font = this.options.defaultFont
|
const font = this.options.defaultFont
|
||||||
|
const size = this.options.defaultSize
|
||||||
const rowMargin = this.options.defaultRowMargin
|
const rowMargin = this.options.defaultRowMargin
|
||||||
const painter = !!this.draw.getPainterStyle()
|
const painter = !!this.draw.getPainterStyle()
|
||||||
const undo = this.historyManager.isCanUndo()
|
const undo = this.historyManager.isCanUndo()
|
||||||
@@ -179,6 +189,7 @@ export class RangeManager {
|
|||||||
redo,
|
redo,
|
||||||
painter,
|
painter,
|
||||||
font,
|
font,
|
||||||
|
size,
|
||||||
bold: false,
|
bold: false,
|
||||||
italic: false,
|
italic: false,
|
||||||
underline: false,
|
underline: false,
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ export default class Editor {
|
|||||||
defaultType: 'TEXT',
|
defaultType: 'TEXT',
|
||||||
defaultFont: 'Yahei',
|
defaultFont: 'Yahei',
|
||||||
defaultSize: 16,
|
defaultSize: 16,
|
||||||
|
minSize: 5,
|
||||||
|
maxSize: 72,
|
||||||
defaultRowMargin: 1,
|
defaultRowMargin: 1,
|
||||||
defaultBasicRowMarginHeight: 8,
|
defaultBasicRowMarginHeight: 8,
|
||||||
defaultTabWidth: 32,
|
defaultTabWidth: 32,
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ export interface IEditorOption {
|
|||||||
defaultType?: string;
|
defaultType?: string;
|
||||||
defaultFont?: string;
|
defaultFont?: string;
|
||||||
defaultSize?: number;
|
defaultSize?: number;
|
||||||
|
minSize?: number;
|
||||||
|
maxSize?: number;
|
||||||
defaultBasicRowMarginHeight?: number;
|
defaultBasicRowMarginHeight?: number;
|
||||||
defaultRowMargin?: number;
|
defaultRowMargin?: number;
|
||||||
defaultTabWidth?: number;
|
defaultTabWidth?: number;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export interface IRangeStyle {
|
|||||||
redo: boolean;
|
redo: boolean;
|
||||||
painter: boolean;
|
painter: boolean;
|
||||||
font: string;
|
font: string;
|
||||||
|
size: number;
|
||||||
bold: boolean;
|
bold: boolean;
|
||||||
italic: boolean;
|
italic: boolean;
|
||||||
underline: boolean;
|
underline: boolean;
|
||||||
|
|||||||
+21
@@ -81,6 +81,19 @@ window.onload = function () {
|
|||||||
instance.command.executeFont(li.dataset.family!)
|
instance.command.executeFont(li.dataset.family!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sizeSetDom = document.querySelector<HTMLDivElement>('.menu-item__size')!
|
||||||
|
const sizeSelectDom = sizeSetDom.querySelector<HTMLDivElement>('.select')!
|
||||||
|
const sizeOptionDom = sizeSetDom.querySelector<HTMLDivElement>('.options')!
|
||||||
|
sizeSetDom.title = `设置字号`
|
||||||
|
sizeSetDom.onclick = function () {
|
||||||
|
console.log('size')
|
||||||
|
sizeOptionDom.classList.toggle('visible')
|
||||||
|
}
|
||||||
|
sizeOptionDom.onclick = function (evt) {
|
||||||
|
const li = evt.target as HTMLLIElement
|
||||||
|
instance.command.executeSize(Number(li.dataset.size!))
|
||||||
|
}
|
||||||
|
|
||||||
const sizeAddDom = document.querySelector<HTMLDivElement>('.menu-item__size-add')!
|
const sizeAddDom = document.querySelector<HTMLDivElement>('.menu-item__size-add')!
|
||||||
sizeAddDom.title = `增大字号(${isApple ? '⌘' : 'Ctrl'}+[)`
|
sizeAddDom.title = `增大字号(${isApple ? '⌘' : 'Ctrl'}+[)`
|
||||||
sizeAddDom.onclick = function () {
|
sizeAddDom.onclick = function () {
|
||||||
@@ -984,6 +997,14 @@ window.onload = function () {
|
|||||||
fontSelectDom.style.fontFamily = payload.font
|
fontSelectDom.style.fontFamily = payload.font
|
||||||
curFontDom.classList.add('active')
|
curFontDom.classList.add('active')
|
||||||
}
|
}
|
||||||
|
sizeOptionDom.querySelectorAll<HTMLLIElement>('li').forEach(li => li.classList.remove('active'))
|
||||||
|
const curSizeDom = sizeOptionDom.querySelector<HTMLLIElement>(`[data-size='${payload.size}']`)
|
||||||
|
if (curSizeDom) {
|
||||||
|
sizeSelectDom.innerText = curSizeDom.innerText
|
||||||
|
curSizeDom.classList.add('active')
|
||||||
|
} else {
|
||||||
|
sizeSelectDom.innerText = `${payload.size}`
|
||||||
|
}
|
||||||
payload.bold ? boldDom.classList.add('active') : boldDom.classList.remove('active')
|
payload.bold ? boldDom.classList.add('active') : boldDom.classList.remove('active')
|
||||||
payload.italic ? italicDom.classList.add('active') : italicDom.classList.remove('active')
|
payload.italic ? italicDom.classList.add('active') : italicDom.classList.remove('active')
|
||||||
payload.underline ? underlineDom.classList.add('active') : underlineDom.classList.remove('active')
|
payload.underline ? underlineDom.classList.add('active') : underlineDom.classList.remove('active')
|
||||||
|
|||||||
+8
-1
@@ -161,7 +161,14 @@ ul {
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-item__font .select {
|
.menu-item .menu-item__size {
|
||||||
|
width: 50px;
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item__font .select,
|
||||||
|
.menu-item__size .select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user