快捷设置文本样式

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

View File

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