feat:增加格式刷
This commit is contained in:
@@ -4,6 +4,7 @@ export class Command {
|
|||||||
|
|
||||||
private static undo: Function
|
private static undo: Function
|
||||||
private static redo: Function
|
private static redo: Function
|
||||||
|
private static painter: Function
|
||||||
private static format: Function
|
private static format: Function
|
||||||
private static bold: Function
|
private static bold: Function
|
||||||
private static print: Function
|
private static print: Function
|
||||||
@@ -11,6 +12,7 @@ export class Command {
|
|||||||
constructor(adapt: CommandAdapt) {
|
constructor(adapt: CommandAdapt) {
|
||||||
Command.undo = adapt.undo.bind(adapt)
|
Command.undo = adapt.undo.bind(adapt)
|
||||||
Command.redo = adapt.redo.bind(adapt)
|
Command.redo = adapt.redo.bind(adapt)
|
||||||
|
Command.painter = adapt.painter.bind(adapt)
|
||||||
Command.print = adapt.print.bind(adapt)
|
Command.print = adapt.print.bind(adapt)
|
||||||
Command.format = adapt.format.bind(adapt)
|
Command.format = adapt.format.bind(adapt)
|
||||||
Command.bold = adapt.bold.bind(adapt)
|
Command.bold = adapt.bold.bind(adapt)
|
||||||
@@ -25,6 +27,10 @@ export class Command {
|
|||||||
return Command.redo()
|
return Command.redo()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public executePainter() {
|
||||||
|
return Command.painter()
|
||||||
|
}
|
||||||
|
|
||||||
public executeFormat() {
|
public executeFormat() {
|
||||||
return Command.format()
|
return Command.format()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { ElementStyleKey } from "../../dataset/enum/ElementStyle"
|
||||||
|
import { IElementStyle } from "../../interface/Element"
|
||||||
import { printImageBase64 } from "../../utils/print"
|
import { printImageBase64 } from "../../utils/print"
|
||||||
import { Draw } from "../draw/Draw"
|
import { Draw } from "../draw/Draw"
|
||||||
import { HistoryManager } from "../history/HistoryManager"
|
import { HistoryManager } from "../history/HistoryManager"
|
||||||
@@ -23,30 +25,42 @@ export class CommandAdapt {
|
|||||||
return this.historyManager.redo()
|
return this.historyManager.redo()
|
||||||
}
|
}
|
||||||
|
|
||||||
public format() {
|
public painter() {
|
||||||
const { startIndex, endIndex } = this.range.getRange()
|
const selection = this.range.getSelection()
|
||||||
if (startIndex === endIndex) return
|
if (!selection) return
|
||||||
const elementList = this.draw.getElementList()
|
const painterStyle: IElementStyle = {}
|
||||||
elementList.slice(startIndex + 1, endIndex + 1)
|
selection.forEach(s => {
|
||||||
.forEach(el => {
|
const painterStyleKeys = ['bold', 'color', 'font', 'size', 'italic', 'underline', 'strikeout']
|
||||||
el.font = ''
|
painterStyleKeys.forEach(p => {
|
||||||
el.color = ''
|
const key = p as keyof typeof ElementStyleKey
|
||||||
el.bold = false
|
if (painterStyle[key] === undefined && s[key] !== undefined) {
|
||||||
el.italic = false
|
painterStyle[key] = s[key] as any
|
||||||
el.underline = false
|
}
|
||||||
el.strikeout = false
|
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
this.draw.setPainterStyle(painterStyle)
|
||||||
|
}
|
||||||
|
|
||||||
|
public format() {
|
||||||
|
const selection = this.range.getSelection()
|
||||||
|
if (!selection) return
|
||||||
|
selection.forEach(el => {
|
||||||
|
el.font = ''
|
||||||
|
el.color = ''
|
||||||
|
el.bold = false
|
||||||
|
el.italic = false
|
||||||
|
el.underline = false
|
||||||
|
el.strikeout = false
|
||||||
|
})
|
||||||
this.draw.render({ isSetCursor: false })
|
this.draw.render({ isSetCursor: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
public bold() {
|
public bold() {
|
||||||
const { startIndex, endIndex } = this.range.getRange()
|
const selection = this.range.getSelection()
|
||||||
if (startIndex === endIndex) return
|
if (!selection) return
|
||||||
const elementList = this.draw.getElementList()
|
selection.forEach(el => {
|
||||||
elementList.slice(startIndex + 1, endIndex + 1)
|
el.bold = true
|
||||||
.forEach(el => {
|
})
|
||||||
el.bold = true
|
|
||||||
})
|
|
||||||
this.draw.render({ isSetCursor: false })
|
this.draw.render({ isSetCursor: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ZERO } from "../../dataset/constant/Common"
|
import { ZERO } from "../../dataset/constant/Common"
|
||||||
import { IDrawOption } from "../../interface/Draw"
|
import { IDrawOption } from "../../interface/Draw"
|
||||||
import { IEditorOption } from "../../interface/Editor"
|
import { IEditorOption } from "../../interface/Editor"
|
||||||
import { IElement, IElementPosition } from "../../interface/Element"
|
import { IElement, IElementPosition, IElementStyle } from "../../interface/Element"
|
||||||
import { IRow } from "../../interface/Row"
|
import { IRow } from "../../interface/Row"
|
||||||
import { deepClone } from "../../utils"
|
import { deepClone } from "../../utils"
|
||||||
import { Cursor } from "../cursor/Cursor"
|
import { Cursor } from "../cursor/Cursor"
|
||||||
@@ -28,6 +28,7 @@ export class Draw {
|
|||||||
private historyManager: HistoryManager
|
private historyManager: HistoryManager
|
||||||
|
|
||||||
private rowCount: number
|
private rowCount: number
|
||||||
|
private painterStyle: IElementStyle | null
|
||||||
|
|
||||||
constructor(canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D, options: Required<IEditorOption>, elementList: IElement[]) {
|
constructor(canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D, options: Required<IEditorOption>, elementList: IElement[]) {
|
||||||
this.canvas = canvas
|
this.canvas = canvas
|
||||||
@@ -37,7 +38,7 @@ export class Draw {
|
|||||||
|
|
||||||
this.historyManager = new HistoryManager()
|
this.historyManager = new HistoryManager()
|
||||||
this.position = new Position(this)
|
this.position = new Position(this)
|
||||||
this.range = new RangeManager(ctx, options)
|
this.range = new RangeManager(ctx, elementList, options)
|
||||||
this.margin = new Margin(ctx, options)
|
this.margin = new Margin(ctx, options)
|
||||||
this.background = new Background(ctx)
|
this.background = new Background(ctx)
|
||||||
|
|
||||||
@@ -48,6 +49,7 @@ export class Draw {
|
|||||||
globalEvent.register()
|
globalEvent.register()
|
||||||
|
|
||||||
this.rowCount = 0
|
this.rowCount = 0
|
||||||
|
this.painterStyle = null
|
||||||
}
|
}
|
||||||
|
|
||||||
public getHistoryManager(): HistoryManager {
|
public getHistoryManager(): HistoryManager {
|
||||||
@@ -78,6 +80,17 @@ export class Draw {
|
|||||||
return this.canvas.toDataURL()
|
return this.canvas.toDataURL()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getPainterStyle(): IElementStyle | null {
|
||||||
|
return this.painterStyle && Object.keys(this.painterStyle).length ? this.painterStyle : null
|
||||||
|
}
|
||||||
|
|
||||||
|
public setPainterStyle(payload: IElementStyle | null) {
|
||||||
|
this.painterStyle = payload
|
||||||
|
if (this.getPainterStyle()) {
|
||||||
|
this.canvas.style.cursor = 'copy'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public render(payload?: IDrawOption) {
|
public render(payload?: IDrawOption) {
|
||||||
let { curIndex, isSubmitHistory = true, isSetCursor = true } = payload || {}
|
let { curIndex, isSubmitHistory = true, isSetCursor = true } = payload || {}
|
||||||
// 清除光标
|
// 清除光标
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { ZERO } from "../../dataset/constant/Common"
|
import { ZERO } from "../../dataset/constant/Common"
|
||||||
|
import { ElementStyleKey } from "../../dataset/enum/ElementStyle"
|
||||||
import { KeyMap } from "../../dataset/enum/Keymap"
|
import { KeyMap } from "../../dataset/enum/Keymap"
|
||||||
import { IElement } from "../../interface/Element"
|
import { IElement } from "../../interface/Element"
|
||||||
import { writeText } from "../../utils/clipboard"
|
import { writeText } from "../../utils/clipboard"
|
||||||
@@ -45,6 +46,23 @@ export class CanvasEvent {
|
|||||||
|
|
||||||
public setIsAllowDrag(payload: boolean) {
|
public setIsAllowDrag(payload: boolean) {
|
||||||
this.isAllowDrag = payload
|
this.isAllowDrag = payload
|
||||||
|
if (payload === false) {
|
||||||
|
this.canvas.style.cursor = 'text'
|
||||||
|
// 应用格式刷样式
|
||||||
|
const painterStyle = this.draw.getPainterStyle()
|
||||||
|
if (!painterStyle) return
|
||||||
|
const selection = this.range.getSelection()
|
||||||
|
if (!selection) return
|
||||||
|
const painterStyleKeys = Object.keys(painterStyle)
|
||||||
|
selection.forEach(s => {
|
||||||
|
painterStyleKeys.forEach(pKey => {
|
||||||
|
const key = pKey as keyof typeof ElementStyleKey
|
||||||
|
s[key] = painterStyle[key] as any
|
||||||
|
})
|
||||||
|
})
|
||||||
|
this.draw.setPainterStyle(null)
|
||||||
|
this.draw.render({ isSetCursor: false })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public mousemove(evt: MouseEvent) {
|
public mousemove(evt: MouseEvent) {
|
||||||
@@ -75,7 +93,7 @@ export class CanvasEvent {
|
|||||||
// 是否还在canvas内部
|
// 是否还在canvas内部
|
||||||
const { x, y, width, height } = this.canvas.getBoundingClientRect()
|
const { x, y, width, height } = this.canvas.getBoundingClientRect()
|
||||||
if (evt.x >= x && evt.x <= x + width && evt.y >= y && evt.y <= y + height) return
|
if (evt.x >= x && evt.x <= x + width && evt.y >= y && evt.y <= y + height) return
|
||||||
this.isAllowDrag = false
|
this.setIsAllowDrag(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
public keydown(evt: KeyboardEvent) {
|
public keydown(evt: KeyboardEvent) {
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
import { IEditorOption } from "../../interface/Editor"
|
import { IEditorOption } from "../../interface/Editor"
|
||||||
|
import { IElement } from "../../interface/Element"
|
||||||
import { IRange } from "../../interface/Range"
|
import { IRange } from "../../interface/Range"
|
||||||
|
|
||||||
export class RangeManager {
|
export class RangeManager {
|
||||||
|
|
||||||
private ctx: CanvasRenderingContext2D
|
private ctx: CanvasRenderingContext2D
|
||||||
|
private elementList: IElement[]
|
||||||
private options: Required<IEditorOption>
|
private options: Required<IEditorOption>
|
||||||
private range: IRange
|
private range: IRange
|
||||||
|
|
||||||
constructor(ctx: CanvasRenderingContext2D, options: Required<IEditorOption>,) {
|
constructor(ctx: CanvasRenderingContext2D, elementList: IElement[], options: Required<IEditorOption>,) {
|
||||||
this.ctx = ctx
|
this.ctx = ctx
|
||||||
|
this.elementList = elementList
|
||||||
this.options = options
|
this.options = options
|
||||||
this.range = {
|
this.range = {
|
||||||
startIndex: 0,
|
startIndex: 0,
|
||||||
@@ -20,6 +23,12 @@ export class RangeManager {
|
|||||||
return this.range
|
return this.range
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getSelection(): IElement[] | null {
|
||||||
|
const { startIndex, endIndex } = this.range
|
||||||
|
if (startIndex === endIndex) return null
|
||||||
|
return this.elementList.slice(startIndex + 1, endIndex + 1)
|
||||||
|
}
|
||||||
|
|
||||||
public setRange(startIndex: number, endIndex: number) {
|
public setRange(startIndex: number, endIndex: number) {
|
||||||
this.range.startIndex = startIndex
|
this.range.startIndex = startIndex
|
||||||
this.range.endIndex = endIndex
|
this.range.endIndex = endIndex
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export enum ElementStyleKey {
|
||||||
|
font = 'font',
|
||||||
|
size = 'size',
|
||||||
|
width = 'width',
|
||||||
|
height = 'height',
|
||||||
|
bold = 'bold',
|
||||||
|
color = 'color',
|
||||||
|
italic = 'italic',
|
||||||
|
underline = 'underline',
|
||||||
|
strikeout = 'strikeout'
|
||||||
|
}
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
export interface IElement {
|
export interface IElementStyle {
|
||||||
type?: 'TEXT' | 'IMAGE';
|
|
||||||
value: string;
|
|
||||||
font?: string;
|
font?: string;
|
||||||
size?: number;
|
size?: number;
|
||||||
width?: number;
|
width?: number;
|
||||||
@@ -12,6 +10,13 @@ export interface IElement {
|
|||||||
strikeout?: boolean;
|
strikeout?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IElementBasic {
|
||||||
|
type?: 'TEXT' | 'IMAGE';
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IElement = IElementBasic & IElementStyle
|
||||||
|
|
||||||
export interface IElementPosition {
|
export interface IElementPosition {
|
||||||
index: number;
|
index: number;
|
||||||
value: string,
|
value: string,
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ window.onload = function () {
|
|||||||
console.log('redo')
|
console.log('redo')
|
||||||
instance.command.executeRedo()
|
instance.command.executeRedo()
|
||||||
}
|
}
|
||||||
|
document.querySelector<HTMLDivElement>('.menu-item__painter')!.onclick = function () {
|
||||||
|
console.log('painter')
|
||||||
|
instance.command.executePainter()
|
||||||
|
}
|
||||||
document.querySelector<HTMLDivElement>('.menu-item__format')!.onclick = function () {
|
document.querySelector<HTMLDivElement>('.menu-item__format')!.onclick = function () {
|
||||||
console.log('format')
|
console.log('format')
|
||||||
instance.command.executeFormat()
|
instance.command.executeFormat()
|
||||||
|
|||||||
Reference in New Issue
Block a user