优化富文本编辑

This commit is contained in:
wanglin2 2023-04-20 09:40:47 +08:00
parent c7e91cc9eb
commit 0f7dc949a4
3 changed files with 46 additions and 20 deletions

View File

@ -1,6 +1,5 @@
import Quill from 'quill' import Quill from 'quill'
import 'quill/dist/quill.snow.css' import 'quill/dist/quill.snow.css'
import './css/quill.css'
import html2canvas from 'html2canvas' import html2canvas from 'html2canvas'
import { Image as SvgImage } from '@svgdotjs/svg.js' import { Image as SvgImage } from '@svgdotjs/svg.js'
import { walk } from './utils' import { walk } from './utils'
@ -41,8 +40,39 @@ class RichText {
this.range = null this.range = null
this.lastRange = null this.lastRange = null
this.node = null this.node = null
this.styleEl = null
this.initOpt() this.initOpt()
this.extendQuill() this.extendQuill()
this.appendCss()
}
// 插入样式
appendCss() {
let cssText = `
.ql-editor {
overflow: hidden;
padding: 0;
height: auto;
line-height: normal;
}
.ql-container {
height: auto;
font-size: inherit;
}
.smm-richtext-node-wrap p {
display: flex;
}
.smm-richtext-node-edit-wrap p {
display: flex;
}
`
this.styleEl = document.createElement('style')
this.styleEl.type = 'text/css'
this.styleEl.innerHTML = cssText
document.head.appendChild(this.styleEl)
} }
// 处理选项参数 // 处理选项参数
@ -96,9 +126,12 @@ class RichText {
if (!rect) rect = node._textData.node.node.getBoundingClientRect() if (!rect) rect = node._textData.node.node.getBoundingClientRect()
this.mindMap.emit('before_show_text_edit') this.mindMap.emit('before_show_text_edit')
this.mindMap.renderer.textEdit.registerTmpShortcut() this.mindMap.renderer.textEdit.registerTmpShortcut()
const paddingX = 5
const paddingY = 3
if (!this.textEditNode) { if (!this.textEditNode) {
this.textEditNode = document.createElement('div') this.textEditNode = document.createElement('div')
this.textEditNode.style.cssText = `position:fixed;box-sizing: border-box;box-shadow: 0 0 20px rgba(0,0,0,.5);outline: none; word-break: break-all;padding: 3px 5px;margin-left: -5px;margin-top: -3px;` this.textEditNode.classList.add('smm-richtext-node-edit-wrap')
this.textEditNode.style.cssText = `position:fixed;box-sizing: border-box;box-shadow: 0 0 20px rgba(0,0,0,.5);outline: none; word-break: break-all;padding: ${paddingY}px ${paddingX}px;margin-left: -${paddingX}px;margin-top: -${paddingY}px;`
this.textEditNode.addEventListener('click', e => { this.textEditNode.addEventListener('click', e => {
e.stopPropagation() e.stopPropagation()
}) })
@ -112,14 +145,14 @@ class RichText {
let bgColor = node.style.merge('fillColor') let bgColor = node.style.merge('fillColor')
this.textEditNode.style.zIndex = this.mindMap.opt.nodeTextEditZIndex this.textEditNode.style.zIndex = this.mindMap.opt.nodeTextEditZIndex
this.textEditNode.style.backgroundColor = bgColor === 'transparent' ? '#fff' : bgColor this.textEditNode.style.backgroundColor = bgColor === 'transparent' ? '#fff' : bgColor
this.textEditNode.style.minWidth = originWidth + 'px' this.textEditNode.style.minWidth = originWidth + paddingX * 2 + 'px'
this.textEditNode.style.minHeight = originHeight + 'px' this.textEditNode.style.minHeight = originHeight + 'px'
this.textEditNode.style.left = this.textEditNode.style.left =
rect.left + (rect.width - originWidth) / 2 + 'px' rect.left + (rect.width - originWidth) / 2 + 'px'
this.textEditNode.style.top = this.textEditNode.style.top =
rect.top + (rect.height - originHeight) / 2 + 'px' rect.top + (rect.height - originHeight) / 2 + 'px'
this.textEditNode.style.display = 'block' this.textEditNode.style.display = 'block'
this.textEditNode.style.maxWidth = this.mindMap.opt.textAutoWrapWidth + 'px' this.textEditNode.style.maxWidth = this.mindMap.opt.textAutoWrapWidth + paddingX * 2 + 'px'
this.textEditNode.style.transform = `scale(${rect.width / originWidth}, ${ this.textEditNode.style.transform = `scale(${rect.width / originWidth}, ${
rect.height / originHeight rect.height / originHeight
})` })`
@ -458,6 +491,7 @@ class RichText {
// 插件被移除前做的事情 // 插件被移除前做的事情
beforePluginRemove() { beforePluginRemove() {
this.transformAllNodesToNormalNode() this.transformAllNodesToNormalNode()
document.head.removeChild(this.styleEl)
} }
} }

View File

@ -1,11 +0,0 @@
.ql-editor {
overflow: hidden;
padding: 0;
height: auto;
line-height: normal;
}
.ql-container {
height: auto;
font-size: inherit;
}

View File

@ -57,6 +57,7 @@ function createRichTextNode() {
div.innerHTML = html div.innerHTML = html
div.style.cssText = `position: fixed; left: -999999px;` div.style.cssText = `position: fixed; left: -999999px;`
let el = div.children[0] let el = div.children[0]
el.classList.add('smm-richtext-node-wrap')
el.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml') el.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')
el.style.maxWidth = this.mindMap.opt.textAutoWrapWidth + 'px' el.style.maxWidth = this.mindMap.opt.textAutoWrapWidth + 'px'
this.mindMap.el.appendChild(div) this.mindMap.el.appendChild(div)
@ -100,11 +101,13 @@ function createTextNode() {
let lines = [] let lines = []
let line = [] let line = []
while (arr.length) { while (arr.length) {
line.push(arr.shift()) let str = arr.shift()
let text = line.join('') let text = [...line, str].join('')
if (measureText(text, textStyle).width >= maxWidth) { if (measureText(text, textStyle).width <= maxWidth) {
lines.push(text) line.push(str)
line = [] } else {
lines.push(line.join(''))
line = [str]
} }
} }
if (line.length > 0) { if (line.length > 0) {