Feat:去除创建隐藏输入框,通过navigator.clipboard实现复制粘贴
This commit is contained in:
parent
4d69778a50
commit
c6a3f4ac7b
@ -127,10 +127,7 @@ export const defaultOpt = {
|
|||||||
customInnerElsAppendTo: null,
|
customInnerElsAppendTo: null,
|
||||||
// 拖拽元素时,指示元素新位置的块的最大高度
|
// 拖拽元素时,指示元素新位置的块的最大高度
|
||||||
nodeDragPlaceholderMaxSize: 20,
|
nodeDragPlaceholderMaxSize: 20,
|
||||||
// 是否允许创建一个隐藏的输入框,该输入框会在节点激活时聚焦,用于粘贴数据和自动进入文本编辑状态
|
|
||||||
enableCreateHiddenInput: true,
|
|
||||||
// 是否在存在一个激活节点时,当按下中文、英文、数字按键时自动进入文本编辑模式
|
// 是否在存在一个激活节点时,当按下中文、英文、数字按键时自动进入文本编辑模式
|
||||||
// 该配置在enableCreateHiddenInput设为true时生效
|
|
||||||
enableAutoEnterTextEditWhenKeydown: true,
|
enableAutoEnterTextEditWhenKeydown: true,
|
||||||
// 设置富文本节点编辑框和节点大小一致,形成伪原地编辑的效果
|
// 设置富文本节点编辑框和节点大小一致,形成伪原地编辑的效果
|
||||||
// 需要注意的是,只有当节点内只有文本、且形状是矩形才会有比较好的效果
|
// 需要注意的是,只有当节点内只有文本、且形状是矩形才会有比较好的效果
|
||||||
|
|||||||
@ -108,10 +108,6 @@ class Render {
|
|||||||
this.mindMap.execCommand('CLEAR_ACTIVE_NODE')
|
this.mindMap.execCommand('CLEAR_ACTIVE_NODE')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// 粘贴事件
|
|
||||||
this.mindMap.on('paste', data => {
|
|
||||||
this.onPaste(data)
|
|
||||||
})
|
|
||||||
// let timer = null
|
// let timer = null
|
||||||
// this.mindMap.on('view_data_change', () => {
|
// this.mindMap.on('view_data_change', () => {
|
||||||
// clearTimeout(timer)
|
// clearTimeout(timer)
|
||||||
@ -273,8 +269,7 @@ class Render {
|
|||||||
this.copy = this.copy.bind(this)
|
this.copy = this.copy.bind(this)
|
||||||
this.mindMap.keyCommand.addShortcut('Control+c', this.copy)
|
this.mindMap.keyCommand.addShortcut('Control+c', this.copy)
|
||||||
this.mindMap.keyCommand.addShortcut('Control+v', () => {
|
this.mindMap.keyCommand.addShortcut('Control+v', () => {
|
||||||
// 隐藏输入框可能会失去焦点,所以要重新聚焦
|
this.onPaste()
|
||||||
this.textEdit.focusHiddenInput()
|
|
||||||
})
|
})
|
||||||
this.cut = this.cut.bind(this)
|
this.cut = this.cut.bind(this)
|
||||||
this.mindMap.keyCommand.addShortcut('Control+x', this.cut)
|
this.mindMap.keyCommand.addShortcut('Control+x', this.cut)
|
||||||
@ -608,7 +603,28 @@ class Render {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 粘贴事件
|
// 粘贴事件
|
||||||
async onPaste({ text, img }) {
|
async onPaste() {
|
||||||
|
// 读取剪贴板的文字和图片
|
||||||
|
let text = null
|
||||||
|
let img = null
|
||||||
|
if (navigator.clipboard) {
|
||||||
|
try {
|
||||||
|
text = await navigator.clipboard.readText()
|
||||||
|
const items = await navigator.clipboard.read()
|
||||||
|
if (items && items.length > 0) {
|
||||||
|
for (const clipboardItem of items) {
|
||||||
|
for (const type of clipboardItem.types) {
|
||||||
|
if (/^image\//.test(type)) {
|
||||||
|
img = await clipboardItem.getType(type)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
// 检查剪切板数据是否有变化
|
// 检查剪切板数据是否有变化
|
||||||
// 通过图片大小来判断图片是否发生变化,可能是不准确的,但是目前没有其他好方法
|
// 通过图片大小来判断图片是否发生变化,可能是不准确的,但是目前没有其他好方法
|
||||||
const imgSize = img ? img.size : 0
|
const imgSize = img ? img.size : 0
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { getStrWithBrFromHtml, checkNodeOuter, isMobile } from '../../utils'
|
import { getStrWithBrFromHtml, checkNodeOuter } from '../../utils'
|
||||||
|
|
||||||
// 节点文字编辑类
|
// 节点文字编辑类
|
||||||
export default class TextEdit {
|
export default class TextEdit {
|
||||||
@ -10,16 +10,11 @@ export default class TextEdit {
|
|||||||
this.currentNode = null
|
this.currentNode = null
|
||||||
// 文本编辑框
|
// 文本编辑框
|
||||||
this.textEditNode = null
|
this.textEditNode = null
|
||||||
// 隐藏的文本输入框
|
|
||||||
this.hiddenInputEl = null
|
|
||||||
// 节点激活时默认聚焦到隐藏输入框
|
|
||||||
this.enableFocus = true
|
|
||||||
// 文本编辑框是否显示
|
// 文本编辑框是否显示
|
||||||
this.showTextEdit = false
|
this.showTextEdit = false
|
||||||
// 如果编辑过程中缩放画布了,那么缓存当前编辑的内容
|
// 如果编辑过程中缩放画布了,那么缓存当前编辑的内容
|
||||||
this.cacheEditingText = ''
|
this.cacheEditingText = ''
|
||||||
this.bindEvent()
|
this.bindEvent()
|
||||||
this.createHiddenInput()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 事件
|
// 事件
|
||||||
@ -51,10 +46,6 @@ export default class TextEdit {
|
|||||||
this.mindMap.on('before_node_active', () => {
|
this.mindMap.on('before_node_active', () => {
|
||||||
this.hideEditTextBox()
|
this.hideEditTextBox()
|
||||||
})
|
})
|
||||||
// 节点激活事件
|
|
||||||
this.mindMap.on('node_active', () => {
|
|
||||||
this.focusHiddenInput()
|
|
||||||
})
|
|
||||||
// 注册编辑快捷键
|
// 注册编辑快捷键
|
||||||
this.mindMap.keyCommand.addShortcut('F2', () => {
|
this.mindMap.keyCommand.addShortcut('F2', () => {
|
||||||
if (this.renderer.activeNodeList.length <= 0) {
|
if (this.renderer.activeNodeList.length <= 0) {
|
||||||
@ -63,74 +54,29 @@ export default class TextEdit {
|
|||||||
this.show(this.renderer.activeNodeList[0])
|
this.show(this.renderer.activeNodeList[0])
|
||||||
})
|
})
|
||||||
this.mindMap.on('scale', this.onScale)
|
this.mindMap.on('scale', this.onScale)
|
||||||
}
|
// // 监听按键事件,判断是否自动进入文本编辑模式
|
||||||
|
if (this.mindMap.opt.enableAutoEnterTextEditWhenKeydown) {
|
||||||
// 创建一个隐藏的文本输入框
|
window.addEventListener('keydown', e => {
|
||||||
createHiddenInput() {
|
|
||||||
const { enableCreateHiddenInput, enableAutoEnterTextEditWhenKeydown } =
|
|
||||||
this.mindMap.opt
|
|
||||||
if (this.hiddenInputEl || isMobile() || !enableCreateHiddenInput) return
|
|
||||||
this.hiddenInputEl = document.createElement('input')
|
|
||||||
this.hiddenInputEl.type = 'text'
|
|
||||||
this.hiddenInputEl.style.cssText = `
|
|
||||||
position: fixed;
|
|
||||||
left: -99999px;
|
|
||||||
top: -99999px;
|
|
||||||
`
|
|
||||||
// 监听按键事件
|
|
||||||
if (enableAutoEnterTextEditWhenKeydown) {
|
|
||||||
this.hiddenInputEl.addEventListener('keydown', e => {
|
|
||||||
const activeNodeList = this.mindMap.renderer.activeNodeList
|
const activeNodeList = this.mindMap.renderer.activeNodeList
|
||||||
if (activeNodeList.length <= 0 || activeNodeList.length > 1) return
|
if (activeNodeList.length <= 0 || activeNodeList.length > 1) return
|
||||||
const node = activeNodeList[0]
|
const node = activeNodeList[0]
|
||||||
// 当正在输入中文或英文或数字时,如果没有按下组合键,那么自动进入文本编辑模式
|
// 当正在输入中文或英文或数字时,如果没有按下组合键,那么自动进入文本编辑模式
|
||||||
const keyCode = e.keyCode
|
if (node && this.checkIsAutoEnterTextEditKey(e)) {
|
||||||
if (
|
|
||||||
node &&
|
|
||||||
(keyCode === 229 ||
|
|
||||||
(keyCode >= 65 && keyCode <= 90) ||
|
|
||||||
(keyCode >= 48 && keyCode <= 57)) &&
|
|
||||||
!this.mindMap.keyCommand.hasCombinationKey(e)
|
|
||||||
) {
|
|
||||||
this.show(node)
|
this.show(node)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 监听粘贴事件
|
|
||||||
this.hiddenInputEl.addEventListener('paste', async event => {
|
|
||||||
event.preventDefault()
|
|
||||||
const text = (event.clipboardData || window.clipboardData).getData('text')
|
|
||||||
const files = event.clipboardData.files
|
|
||||||
let img = null
|
|
||||||
if (files.length > 0) {
|
|
||||||
for (let i = 0; i < files.length; i++) {
|
|
||||||
if (/^image\//.test(files[i].type)) {
|
|
||||||
img = files[i]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.mindMap.emit('paste', {
|
|
||||||
text,
|
|
||||||
img
|
|
||||||
})
|
|
||||||
})
|
|
||||||
document.body.appendChild(this.hiddenInputEl)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 让隐藏的文本输入框聚焦
|
// 判断是否是自动进入文本编模式的按钮
|
||||||
focusHiddenInput() {
|
checkIsAutoEnterTextEditKey(e) {
|
||||||
if (this.hiddenInputEl && this.enableFocus) this.hiddenInputEl.focus()
|
const keyCode = e.keyCode
|
||||||
}
|
return (
|
||||||
|
(keyCode === 229 ||
|
||||||
// 关闭默认聚焦
|
(keyCode >= 65 && keyCode <= 90) ||
|
||||||
stopFocusOnNodeActive() {
|
(keyCode >= 48 && keyCode <= 57)) &&
|
||||||
this.enableFocus = false
|
!this.mindMap.keyCommand.hasCombinationKey(e)
|
||||||
}
|
)
|
||||||
|
|
||||||
// 开启默认聚焦
|
|
||||||
openFocusOnNodeActive() {
|
|
||||||
this.enableFocus = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注册临时快捷键
|
// 注册临时快捷键
|
||||||
@ -188,6 +134,7 @@ export default class TextEdit {
|
|||||||
|
|
||||||
// 显示文本编辑框
|
// 显示文本编辑框
|
||||||
showEditTextBox(node, rect, isInserting) {
|
showEditTextBox(node, rect, isInserting) {
|
||||||
|
if (this.showTextEdit) return
|
||||||
this.mindMap.emit('before_show_text_edit')
|
this.mindMap.emit('before_show_text_edit')
|
||||||
this.registerTmpShortcut()
|
this.registerTmpShortcut()
|
||||||
if (!this.textEditNode) {
|
if (!this.textEditNode) {
|
||||||
@ -203,6 +150,11 @@ export default class TextEdit {
|
|||||||
this.textEditNode.addEventListener('mousedown', e => {
|
this.textEditNode.addEventListener('mousedown', e => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
})
|
})
|
||||||
|
this.textEditNode.addEventListener('keydown', e => {
|
||||||
|
if (this.checkIsAutoEnterTextEditKey(e)) {
|
||||||
|
e.stopPropagation()
|
||||||
|
}
|
||||||
|
})
|
||||||
const targetNode =
|
const targetNode =
|
||||||
this.mindMap.opt.customInnerElsAppendTo || document.body
|
this.mindMap.opt.customInnerElsAppendTo || document.body
|
||||||
targetNode.appendChild(this.textEditNode)
|
targetNode.appendChild(this.textEditNode)
|
||||||
|
|||||||
@ -198,6 +198,11 @@ class RichText {
|
|||||||
this.textEditNode.addEventListener('mousedown', e => {
|
this.textEditNode.addEventListener('mousedown', e => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
})
|
})
|
||||||
|
this.textEditNode.addEventListener('keydown', e => {
|
||||||
|
if (this.mindMap.renderer.textEdit.checkIsAutoEnterTextEditKey(e)) {
|
||||||
|
e.stopPropagation()
|
||||||
|
}
|
||||||
|
})
|
||||||
const targetNode = customInnerElsAppendTo || document.body
|
const targetNode = customInnerElsAppendTo || document.body
|
||||||
targetNode.appendChild(this.textEditNode)
|
targetNode.appendChild(this.textEditNode)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -258,9 +258,7 @@ export default {
|
|||||||
this.notHandleDataChange = true
|
this.notHandleDataChange = true
|
||||||
const targetNode = this.mindMap.renderer.findNodeByUid(data.uid)
|
const targetNode = this.mindMap.renderer.findNodeByUid(data.uid)
|
||||||
if (targetNode && targetNode.nodeData.data.isActive) return
|
if (targetNode && targetNode.nodeData.data.isActive) return
|
||||||
this.mindMap.renderer.textEdit.stopFocusOnNodeActive()
|
|
||||||
this.mindMap.execCommand('GO_TARGET_NODE', data.uid, () => {
|
this.mindMap.execCommand('GO_TARGET_NODE', data.uid, () => {
|
||||||
this.mindMap.renderer.textEdit.openFocusOnNodeActive()
|
|
||||||
this.notHandleDataChange = false
|
this.notHandleDataChange = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user