优化和修复节点编辑的一些体验和问题

This commit is contained in:
wanglin2 2023-03-31 14:37:32 +08:00
parent f8506cb75b
commit 8d9299aed7
7 changed files with 38 additions and 20 deletions

View File

@ -28,6 +28,7 @@ class Event extends EventEmitter {
// 绑定函数上下文 // 绑定函数上下文
bindFn() { bindFn() {
this.onDrawClick = this.onDrawClick.bind(this) this.onDrawClick = this.onDrawClick.bind(this)
this.onDrawMousedown = this.onDrawMousedown.bind(this)
this.onMousedown = this.onMousedown.bind(this) this.onMousedown = this.onMousedown.bind(this)
this.onMousemove = this.onMousemove.bind(this) this.onMousemove = this.onMousemove.bind(this)
this.onMouseup = this.onMouseup.bind(this) this.onMouseup = this.onMouseup.bind(this)
@ -40,6 +41,7 @@ class Event extends EventEmitter {
// 绑定事件 // 绑定事件
bind() { bind() {
this.mindMap.svg.on('click', this.onDrawClick) this.mindMap.svg.on('click', this.onDrawClick)
this.mindMap.svg.on('mousedown', this.onDrawMousedown)
this.mindMap.el.addEventListener('mousedown', this.onMousedown) this.mindMap.el.addEventListener('mousedown', this.onMousedown)
this.mindMap.svg.on('mousedown', this.onSvgMousedown) this.mindMap.svg.on('mousedown', this.onSvgMousedown)
window.addEventListener('mousemove', this.onMousemove) window.addEventListener('mousemove', this.onMousemove)
@ -52,6 +54,7 @@ class Event extends EventEmitter {
// 解绑事件 // 解绑事件
unbind() { unbind() {
this.mindMap.svg.off('click', this.onDrawClick) this.mindMap.svg.off('click', this.onDrawClick)
this.mindMap.svg.off('mousedown', this.onDrawMousedown)
this.mindMap.el.removeEventListener('mousedown', this.onMousedown) this.mindMap.el.removeEventListener('mousedown', this.onMousedown)
window.removeEventListener('mousemove', this.onMousemove) window.removeEventListener('mousemove', this.onMousemove)
window.removeEventListener('mouseup', this.onMouseup) window.removeEventListener('mouseup', this.onMouseup)
@ -65,6 +68,11 @@ class Event extends EventEmitter {
this.emit('draw_click', e) this.emit('draw_click', e)
} }
// 画布的鼠标按下事件
onDrawMousedown(e) {
this.emit('draw_mousedown', e)
}
// svg画布的鼠标按下事件 // svg画布的鼠标按下事件
onSvgMousedown(e) { onSvgMousedown(e) {
this.emit('svg_mousedown', e) this.emit('svg_mousedown', e)
@ -72,7 +80,6 @@ class Event extends EventEmitter {
// 鼠标按下事件 // 鼠标按下事件
onMousedown(e) { onMousedown(e) {
// e.preventDefault()
// 鼠标左键 // 鼠标左键
if (e.which === 1) { if (e.which === 1) {
this.isLeftMousedown = true this.isLeftMousedown = true
@ -84,13 +91,13 @@ class Event extends EventEmitter {
// 鼠标移动事件 // 鼠标移动事件
onMousemove(e) { onMousemove(e) {
// e.preventDefault()
this.mousemovePos.x = e.clientX this.mousemovePos.x = e.clientX
this.mousemovePos.y = e.clientY this.mousemovePos.y = e.clientY
this.mousemoveOffset.x = e.clientX - this.mousedownPos.x this.mousemoveOffset.x = e.clientX - this.mousedownPos.x
this.mousemoveOffset.y = e.clientY - this.mousedownPos.y this.mousemoveOffset.y = e.clientY - this.mousedownPos.y
this.emit('mousemove', e, this) this.emit('mousemove', e, this)
if (this.isLeftMousedown) { if (this.isLeftMousedown) {
e.preventDefault()
this.emit('drag', e, this) this.emit('drag', e, this)
} }
} }

View File

@ -450,6 +450,7 @@ class Node {
// 更新节点形状样式 // 更新节点形状样式
updateNodeShape() { updateNodeShape() {
if (!this.shapeNode) return
const shape = this.getShape() const shape = this.getShape()
this.style[shape === CONSTANTS.SHAPE.RECTANGLE ? 'rect' : 'shape'](this.shapeNode) this.style[shape === CONSTANTS.SHAPE.RECTANGLE ? 'rect' : 'shape'](this.shapeNode)
} }

View File

@ -4,6 +4,7 @@ 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'
import { CONSTANTS } from './utils/constant'
let extended = false let extended = false
@ -97,7 +98,7 @@ class RichText {
this.mindMap.renderer.textEdit.registerTmpShortcut() this.mindMap.renderer.textEdit.registerTmpShortcut()
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;` 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;`
document.body.appendChild(this.textEditNode) document.body.appendChild(this.textEditNode)
} }
// 原始宽高 // 原始宽高
@ -147,7 +148,7 @@ class RichText {
underline: node.style.merge('textDecoration') === 'underline', underline: node.style.merge('textDecoration') === 'underline',
strike: node.style.merge('textDecoration') === 'line-through' strike: node.style.merge('textDecoration') === 'line-through'
} }
this.formatText(style) this.formatAllText(style)
} }
// 隐藏文本编辑控件,即完成编辑 // 隐藏文本编辑控件,即完成编辑
@ -435,6 +436,7 @@ class RichText {
node.data.richText = false node.data.richText = false
div.innerHTML = node.data.text div.innerHTML = node.data.text
node.data.text = div.textContent node.data.text = div.textContent
// delete node.data.uid
} }
}, },
null, null,
@ -445,7 +447,7 @@ class RichText {
// 清空历史数据,并且触发数据变化 // 清空历史数据,并且触发数据变化
this.mindMap.command.clearHistory() this.mindMap.command.clearHistory()
this.mindMap.command.addHistory() this.mindMap.command.addHistory()
this.mindMap.reRender() this.mindMap.render(null, CONSTANTS.TRANSFORM_TO_NORMAL_NODE)
} }
// 插件被移除前做的事情 // 插件被移除前做的事情

View File

@ -79,14 +79,14 @@ class Style {
color: this.merge('fillColor') color: this.merge('fillColor')
}) })
// 节点使用横线样式,不需要渲染非激活状态的边框样式 // 节点使用横线样式,不需要渲染非激活状态的边框样式
if ( // if (
!this.ctx.isRoot && // !this.ctx.isRoot &&
!this.ctx.isGeneralization && // !this.ctx.isGeneralization &&
this.ctx.mindMap.themeConfig.nodeUseLineStyle && // this.ctx.mindMap.themeConfig.nodeUseLineStyle &&
!this.ctx.nodeData.data.isActive // !this.ctx.nodeData.data.isActive
) { // ) {
return // return
} // }
node.stroke({ node.stroke({
color: this.merge('borderColor'), color: this.merge('borderColor'),
width: this.merge('borderWidth'), width: this.merge('borderWidth'),
@ -120,11 +120,11 @@ class Style {
} }
// html文字节点 // html文字节点
domText(node, fontSizeScale = 1) { domText(node, fontSizeScale = 1, textLines) {
node.style.fontFamily = this.merge('fontFamily') node.style.fontFamily = this.merge('fontFamily')
node.style.fontSize = this.merge('fontSize') * fontSizeScale + 'px' node.style.fontSize = this.merge('fontSize') * fontSizeScale + 'px'
node.style.fontWeight = this.merge('fontWeight') || 'normal' node.style.fontWeight = this.merge('fontWeight') || 'normal'
node.style.lineHeight = this.merge('lineHeight') node.style.lineHeight = textLines === 1 ? 'normal' : this.merge('lineHeight')
node.style.fontStyle = this.merge('fontStyle') node.style.fontStyle = this.merge('fontStyle')
} }

View File

@ -23,6 +23,10 @@ export default class TextEdit {
// 隐藏文本编辑框 // 隐藏文本编辑框
this.hideEditTextBox() this.hideEditTextBox()
}) })
this.mindMap.on('draw_mousedown', () => {
// 隐藏文本编辑框
this.hideEditTextBox()
})
// 展开收缩按钮点击事件 // 展开收缩按钮点击事件
this.mindMap.on('expand_btn_click', () => { this.mindMap.on('expand_btn_click', () => {
this.hideEditTextBox() this.hideEditTextBox()
@ -74,17 +78,18 @@ export default class TextEdit {
let scale = this.mindMap.view.scale let scale = this.mindMap.view.scale
let lineHeight = node.style.merge('lineHeight') let lineHeight = node.style.merge('lineHeight')
let fontSize = node.style.merge('fontSize') let fontSize = node.style.merge('fontSize')
node.style.domText(this.textEditNode, scale) let textLines = node.nodeData.data.text.split(/\n/gim)
this.textEditNode.innerHTML = node.nodeData.data.text node.style.domText(this.textEditNode, scale, textLines.length)
.split(/\n/gim) this.textEditNode.innerHTML = textLines.join('<br>')
.join('<br>')
this.textEditNode.style.minWidth = rect.width + 10 + 'px' this.textEditNode.style.minWidth = rect.width + 10 + 'px'
this.textEditNode.style.minHeight = rect.height + 6 + 'px' this.textEditNode.style.minHeight = rect.height + 6 + 'px'
this.textEditNode.style.left = rect.left + 'px' this.textEditNode.style.left = rect.left + 'px'
this.textEditNode.style.top = rect.top + 'px' this.textEditNode.style.top = rect.top + 'px'
this.textEditNode.style.display = 'block' this.textEditNode.style.display = 'block'
this.textEditNode.style.maxWidth = this.mindMap.opt.textAutoWrapWidth * scale + 'px' this.textEditNode.style.maxWidth = this.mindMap.opt.textAutoWrapWidth * scale + 'px'
this.textEditNode.style.transform = `translateY(${-(lineHeight * fontSize - fontSize) / 2 * scale}px)` if (textLines.length > 1 && lineHeight !== 1) {
this.textEditNode.style.transform = `translateY(${-((lineHeight * fontSize - fontSize) / 2 - 2) * scale}px)`
}
this.showTextEdit = true this.showTextEdit = true
// 选中文本 // 选中文本
this.selectNodeText() this.selectNodeText()
@ -126,6 +131,7 @@ export default class TextEdit {
this.textEditNode.style.fontFamily = 'inherit' this.textEditNode.style.fontFamily = 'inherit'
this.textEditNode.style.fontSize = 'inherit' this.textEditNode.style.fontSize = 'inherit'
this.textEditNode.style.fontWeight = 'normal' this.textEditNode.style.fontWeight = 'normal'
this.textEditNode.style.transform = 'translateY(0)'
this.showTextEdit = false this.showTextEdit = false
} }
} }

View File

@ -2,6 +2,7 @@
overflow: hidden; overflow: hidden;
padding: 0; padding: 0;
height: auto; height: auto;
line-height: normal;
} }
.ql-container { .ql-container {

View File

@ -117,6 +117,7 @@ export const themeList = [
// 常量 // 常量
export const CONSTANTS = { export const CONSTANTS = {
CHANGE_THEME: 'changeTheme', CHANGE_THEME: 'changeTheme',
TRANSFORM_TO_NORMAL_NODE: 'transformAllNodesToNormalNode',
MODE: { MODE: {
READONLY: 'readonly', READONLY: 'readonly',
EDIT: 'edit' EDIT: 'edit'