快捷设置文本样式

This commit is contained in:
pipipi-pikachu 2021-01-28 22:21:09 +08:00
parent ee13b943d5
commit 9f54848f80
2 changed files with 117 additions and 63 deletions

View File

@ -6,6 +6,7 @@
v-for="item in presetStyles" v-for="item in presetStyles"
:key="item.label" :key="item.label"
:style="item.style" :style="item.style"
@click="emitBatchRichTextCommand(item.cmd)"
>{{item.label}}</div> >{{item.label}}</div>
</div> </div>
@ -229,6 +230,12 @@ const presetStyles = [
fontSize: '30px', fontSize: '30px',
fontWeight: 700, fontWeight: 700,
}, },
cmd: [
{ command: 'clear' },
{ command: 'fontsize', value: '48px' },
{ command: 'align', value: 'center' },
{ command: 'bold' },
],
}, },
{ {
label: '小标题', label: '小标题',
@ -236,12 +243,22 @@ const presetStyles = [
fontSize: '24px', fontSize: '24px',
fontWeight: 700, fontWeight: 700,
}, },
cmd: [
{ command: 'clear' },
{ command: 'fontsize', value: '36px' },
{ command: 'align', value: 'center' },
{ command: 'bold' },
],
}, },
{ {
label: '正文', label: '正文',
style: { style: {
fontSize: '20px', fontSize: '20px',
}, },
cmd: [
{ command: 'clear' },
{ command: 'fontsize', value: '20px' },
],
}, },
{ {
label: '注释', label: '注释',
@ -249,9 +266,19 @@ const presetStyles = [
fontSize: '16px', fontSize: '16px',
fontStyle: 'italic', fontStyle: 'italic',
}, },
cmd: [
{ command: 'clear' },
{ command: 'fontsize', value: '16px' },
{ command: 'em' },
],
}, },
] ]
interface CommandPayload {
command: string;
value?: string;
}
export default defineComponent({ export default defineComponent({
name: 'text-style-panel', name: 'text-style-panel',
components: { components: {
@ -312,6 +339,10 @@ export default defineComponent({
emitter.emit(EmitterEvents.EXEC_TEXT_COMMAND, { command, value }) emitter.emit(EmitterEvents.EXEC_TEXT_COMMAND, { command, value })
} }
const emitBatchRichTextCommand = (payload: CommandPayload[]) => {
emitter.emit(EmitterEvents.EXEC_TEXT_COMMAND, payload)
}
const { addHistorySnapshot } = useHistorySnapshot() const { addHistorySnapshot } = useHistorySnapshot()
const updateLineHeight = (value: number) => { const updateLineHeight = (value: number) => {
@ -345,6 +376,7 @@ export default defineComponent({
updateWordSpace, updateWordSpace,
updateFill, updateFill,
emitRichTextCommand, emitRichTextCommand,
emitBatchRichTextCommand,
presetStyles, presetStyles,
} }
}, },

View File

@ -42,18 +42,18 @@ import debounce from 'lodash/debounce'
import { useStore } from 'vuex' import { useStore } from 'vuex'
import { MutationTypes, State } from '@/store' import { MutationTypes, State } from '@/store'
import { EditorView } from 'prosemirror-view' import { EditorView } from 'prosemirror-view'
import { toggleMark, wrapIn, selectAll } from 'prosemirror-commands'
import { PPTTextElement } from '@/types/slides' import { PPTTextElement } from '@/types/slides'
import { ContextmenuItem } from '@/components/Contextmenu/types' import { ContextmenuItem } from '@/components/Contextmenu/types'
import { initProsemirrorEditor } from '@/prosemirror/' import { initProsemirrorEditor } from '@/prosemirror/'
import { getTextAttrs } from '@/prosemirror/utils' import { getTextAttrs } from '@/prosemirror/utils'
import emitter, { EmitterEvents } from '@/utils/emitter' import emitter, { EmitterEvents } from '@/utils/emitter'
import useElementShadow from '@/views/components/element/hooks/useElementShadow' import useElementShadow from '@/views/components/element/hooks/useElementShadow'
import { alignmentCommand } from '@/prosemirror/commands/setTextAlign'
import { toggleList } from '@/prosemirror/commands/toggleList'
import useHistorySnapshot from '@/hooks/useHistorySnapshot' import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import ElementOutline from '@/views/components/element/ElementOutline.vue' import ElementOutline from '@/views/components/element/ElementOutline.vue'
import { toggleMark, wrapIn } from 'prosemirror-commands'
import { alignmentCommand } from '@/prosemirror/commands/setTextAlign'
import { toggleList } from '@/prosemirror/commands/toggleList'
interface CommandPayload { interface CommandPayload {
command: string; command: string;
@ -195,69 +195,91 @@ export default defineComponent({
const handleElementId = computed(() => store.state.handleElementId) const handleElementId = computed(() => store.state.handleElementId)
const execCommand = (payload: CommandPayload) => { const execCommand = (payload: CommandPayload | CommandPayload[]) => {
if(handleElementId.value !== props.elementInfo.id) return if(handleElementId.value !== props.elementInfo.id) return
if(payload.command === 'fontname' && payload.value) { const commands = ('command' in payload) ? [payload] : payload
const mark = editorView.state.schema.marks.fontname.create({ fontname: payload.value })
const { $from, $to } = editorView.state.selection for(const item of commands) {
editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark)) if(item.command === 'fontname' && item.value) {
} const mark = editorView.state.schema.marks.fontname.create({ fontname: item.value })
else if(payload.command === 'fontsize' && payload.value) { const { empty } = editorView.state.selection
const mark = editorView.state.schema.marks.fontsize.create({ fontsize: payload.value }) if(empty) selectAll(editorView.state, editorView.dispatch)
const { $from, $to } = editorView.state.selection const { $from, $to } = editorView.state.selection
editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark)) editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))
} }
else if(payload.command === 'color' && payload.value) { else if(item.command === 'fontsize' && item.value) {
const mark = editorView.state.schema.marks.forecolor.create({ color: payload.value }) const mark = editorView.state.schema.marks.fontsize.create({ fontsize: item.value })
const { $from, $to } = editorView.state.selection const { empty } = editorView.state.selection
editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark)) if(empty) selectAll(editorView.state, editorView.dispatch)
} const { $from, $to } = editorView.state.selection
else if(payload.command === 'backcolor' && payload.value) { editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))
const mark = editorView.state.schema.marks.backcolor.create({ backcolor: payload.value }) }
const { $from, $to } = editorView.state.selection else if(item.command === 'color' && item.value) {
editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark)) const mark = editorView.state.schema.marks.forecolor.create({ color: item.value })
} const { empty } = editorView.state.selection
else if(payload.command === 'bold') { if(empty) selectAll(editorView.state, editorView.dispatch)
toggleMark(editorView.state.schema.marks.strong)(editorView.state, editorView.dispatch) const { $from, $to } = editorView.state.selection
} editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))
else if(payload.command === 'em') { }
toggleMark(editorView.state.schema.marks.em)(editorView.state, editorView.dispatch) else if(item.command === 'backcolor' && item.value) {
} const mark = editorView.state.schema.marks.backcolor.create({ backcolor: item.value })
else if(payload.command === 'underline') { const { empty } = editorView.state.selection
toggleMark(editorView.state.schema.marks.underline)(editorView.state, editorView.dispatch) if(empty) selectAll(editorView.state, editorView.dispatch)
} const { $from, $to } = editorView.state.selection
else if(payload.command === 'strikethrough') { editorView.dispatch(editorView.state.tr.addMark($from.pos, $to.pos, mark))
toggleMark(editorView.state.schema.marks.strikethrough)(editorView.state, editorView.dispatch) }
} else if(item.command === 'bold') {
else if(payload.command === 'subscript') { const { empty } = editorView.state.selection
toggleMark(editorView.state.schema.marks.subscript)(editorView.state, editorView.dispatch) if(empty) selectAll(editorView.state, editorView.dispatch)
} toggleMark(editorView.state.schema.marks.strong)(editorView.state, editorView.dispatch)
else if(payload.command === 'superscript') { }
toggleMark(editorView.state.schema.marks.superscript)(editorView.state, editorView.dispatch) else if(item.command === 'em') {
} const { empty } = editorView.state.selection
else if(payload.command === 'blockquote') { if(empty) selectAll(editorView.state, editorView.dispatch)
wrapIn(editorView.state.schema.nodes.blockquote)(editorView.state, editorView.dispatch) toggleMark(editorView.state.schema.marks.em)(editorView.state, editorView.dispatch)
} }
else if(payload.command === 'code') { else if(item.command === 'underline') {
toggleMark(editorView.state.schema.marks.code)(editorView.state, editorView.dispatch) const { empty } = editorView.state.selection
} if(empty) selectAll(editorView.state, editorView.dispatch)
else if(payload.command === 'align' && payload.value) { toggleMark(editorView.state.schema.marks.underline)(editorView.state, editorView.dispatch)
alignmentCommand(editorView, payload.value) }
} else if(item.command === 'strikethrough') {
else if(payload.command === 'bulletList') { const { empty } = editorView.state.selection
const { bullet_list: bulletList, list_item: listItem } = editorView.state.schema.nodes if(empty) selectAll(editorView.state, editorView.dispatch)
toggleList(bulletList, listItem)(editorView.state, editorView.dispatch) toggleMark(editorView.state.schema.marks.strikethrough)(editorView.state, editorView.dispatch)
} }
else if(payload.command === 'orderedList') { else if(item.command === 'subscript') {
const { ordered_list: orderedList, list_item: listItem } = editorView.state.schema.nodes toggleMark(editorView.state.schema.marks.subscript)(editorView.state, editorView.dispatch)
toggleList(orderedList, listItem)(editorView.state, editorView.dispatch) }
} else if(item.command === 'superscript') {
else if(payload.command === 'clear') { toggleMark(editorView.state.schema.marks.superscript)(editorView.state, editorView.dispatch)
if(editorView.state.selection.empty) return false }
const { $from, $to } = editorView.state.selection else if(item.command === 'blockquote') {
editorView.dispatch(editorView.state.tr.removeMark($from.pos, $to.pos)) wrapIn(editorView.state.schema.nodes.blockquote)(editorView.state, editorView.dispatch)
}
else if(item.command === 'code') {
toggleMark(editorView.state.schema.marks.code)(editorView.state, editorView.dispatch)
}
else if(item.command === 'align' && item.value) {
alignmentCommand(editorView, item.value)
}
else if(item.command === 'bulletList') {
const { bullet_list: bulletList, list_item: listItem } = editorView.state.schema.nodes
toggleList(bulletList, listItem)(editorView.state, editorView.dispatch)
}
else if(item.command === 'orderedList') {
const { ordered_list: orderedList, list_item: listItem } = editorView.state.schema.nodes
toggleList(orderedList, listItem)(editorView.state, editorView.dispatch)
}
else if(item.command === 'clear') {
const { empty } = editorView.state.selection
if(empty) selectAll(editorView.state, editorView.dispatch)
const { $from, $to } = editorView.state.selection
editorView.dispatch(editorView.state.tr.removeMark($from.pos, $to.pos))
}
} }
editorView.focus() editorView.focus()
handleInput() handleInput()
handleClick() handleClick()