mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-21 18:37:43 +08:00
317 lines
9.8 KiB
JavaScript
317 lines
9.8 KiB
JavaScript
import {
|
|
bfsWalk,
|
|
throttle
|
|
} from './utils'
|
|
import Base from './layouts/Base'
|
|
|
|
/**
|
|
* javascript comment
|
|
* @Author: 王林25
|
|
* @Date: 2021-11-23 17:38:55
|
|
* @Desc: 节点拖动类
|
|
*/
|
|
class Drag extends Base {
|
|
/**
|
|
* @Author: 王林
|
|
* @Date: 2021-07-10 22:35:16
|
|
* @Desc: 构造函数
|
|
*/
|
|
constructor({
|
|
mindMap
|
|
}) {
|
|
super(mindMap.renderer)
|
|
this.mindMap = mindMap
|
|
this.reset()
|
|
this.bindEvent()
|
|
}
|
|
|
|
/**
|
|
* javascript comment
|
|
* @Author: 王林25
|
|
* @Date: 2021-11-23 19:33:56
|
|
* @Desc: 复位
|
|
*/
|
|
reset() {
|
|
// 当前拖拽节点
|
|
this.node = null
|
|
// 当前重叠节点
|
|
this.overlapNode = null
|
|
// 当前上一个同级节点
|
|
this.prevNode = null
|
|
// 当前下一个同级节点
|
|
this.nextNode = null
|
|
// 画布的变换数据
|
|
this.drawTransform = null
|
|
// 克隆节点
|
|
this.clone = null
|
|
// 连接线
|
|
this.line = null
|
|
// 同级位置占位符
|
|
this.placeholder = null
|
|
// 鼠标按下位置和节点左上角的偏移量
|
|
this.offsetX = 0
|
|
this.offsetY = 0
|
|
// 克隆节点左上角的坐标
|
|
this.cloneNodeLeft = 0
|
|
this.cloneNodeTop = 0
|
|
// 当前鼠标是否按下
|
|
this.isMousedown = false
|
|
// 拖拽的鼠标位置变量
|
|
this.mouseDownX = 0
|
|
this.mouseDownY = 0
|
|
this.mouseMoveX = 0
|
|
this.mouseMoveY = 0
|
|
}
|
|
|
|
/**
|
|
* @Author: 王林
|
|
* @Date: 2021-07-10 22:36:36
|
|
* @Desc: 绑定事件
|
|
*/
|
|
bindEvent() {
|
|
this.checkOverlapNode = throttle(this.checkOverlapNode, 300, this)
|
|
this.mindMap.on('node_mousedown', (node, e) => {
|
|
if (this.mindMap.opt.readonly || node.isGeneralization) {
|
|
return
|
|
}
|
|
if (e.which !== 1 || node.isRoot) {
|
|
return
|
|
}
|
|
e.preventDefault()
|
|
// 计算鼠标按下的位置距离节点左上角的距离
|
|
this.drawTransform = this.mindMap.draw.transform()
|
|
let {
|
|
scaleX,
|
|
scaleY,
|
|
translateX,
|
|
translateY
|
|
} = this.drawTransform
|
|
this.offsetX = e.clientX - (node.left * scaleX + translateX)
|
|
this.offsetY = e.clientY - (node.top * scaleY + translateY)
|
|
//
|
|
this.node = node
|
|
this.isMousedown = true
|
|
let {
|
|
x,
|
|
y
|
|
} = this.mindMap.toPos(e.clientX, e.clientY)
|
|
this.mouseDownX = x
|
|
this.mouseDownY = y
|
|
})
|
|
this.mindMap.on('mousemove', (e) => {
|
|
if (this.mindMap.opt.readonly) {
|
|
return
|
|
}
|
|
if (!this.isMousedown) {
|
|
return
|
|
}
|
|
e.preventDefault()
|
|
let {
|
|
x,
|
|
y
|
|
} = this.mindMap.toPos(e.clientX, e.clientY)
|
|
this.mouseMoveX = x
|
|
this.mouseMoveY = y
|
|
if ((Math.abs(x - this.mouseDownX) <= 10 && Math.abs(y - this.mouseDownY) <= 10) && !this.node.isDrag) {
|
|
return
|
|
}
|
|
this.mindMap.renderer.clearAllActive()
|
|
this.onMove(x, y)
|
|
})
|
|
this.onMouseup = this.onMouseup.bind(this)
|
|
this.mindMap.on('node_mouseup', this.onMouseup)
|
|
this.mindMap.on('mouseup', this.onMouseup)
|
|
}
|
|
|
|
/**
|
|
* javascript comment
|
|
* @Author: 王林25
|
|
* @Date: 2021-11-23 19:38:02
|
|
* @Desc: 鼠标松开事件
|
|
*/
|
|
onMouseup(e) {
|
|
if (!this.isMousedown) {
|
|
return;
|
|
}
|
|
this.isMousedown = false
|
|
let _nodeIsDrag = this.node.isDrag
|
|
this.node.isDrag = false
|
|
this.node.show()
|
|
this.removeCloneNode()
|
|
// 存在重叠子节点,则移动作为其子节点
|
|
if (this.overlapNode) {
|
|
this.mindMap.renderer.setNodeActive(this.overlapNode, false)
|
|
this.mindMap.execCommand('MOVE_NODE_TO', this.node, this.overlapNode)
|
|
} else if (this.prevNode) { // 存在前一个相邻节点,作为其下一个兄弟节点
|
|
this.mindMap.renderer.setNodeActive(this.prevNode, false)
|
|
this.mindMap.execCommand('INSERT_AFTER', this.node, this.prevNode)
|
|
} else if (this.nextNode) { // 存在下一个相邻节点,作为其前一个兄弟节点
|
|
this.mindMap.renderer.setNodeActive(this.nextNode, false)
|
|
this.mindMap.execCommand('INSERT_BEFORE', this.node, this.nextNode)
|
|
} else if (_nodeIsDrag) {
|
|
// 自定义位置
|
|
let {
|
|
x,
|
|
y
|
|
} = this.mindMap.toPos(e.clientX - this.offsetX, e.clientY - this.offsetY)
|
|
let {
|
|
scaleX,
|
|
scaleY,
|
|
translateX,
|
|
translateY
|
|
} = this.drawTransform
|
|
x = (x - translateX) / scaleX
|
|
y = (y - translateY) / scaleY
|
|
this.node.left = x
|
|
this.node.top = y
|
|
this.node.customLeft = x
|
|
this.node.customTop = y
|
|
this.mindMap.execCommand('SET_NODE_CUSTOM_POSITION', this.node, x, y)
|
|
this.mindMap.render()
|
|
}
|
|
this.reset()
|
|
}
|
|
|
|
/**
|
|
* javascript comment
|
|
* @Author: 王林25
|
|
* @Date: 2021-11-23 19:34:53
|
|
* @Desc: 创建克隆节点
|
|
*/
|
|
createCloneNode() {
|
|
if (!this.clone) {
|
|
// 节点
|
|
this.clone = this.node.group.clone()
|
|
this.clone.opacity(0.5)
|
|
this.clone.css('z-index', 99999)
|
|
this.node.isDrag = true
|
|
this.node.hide()
|
|
// 连接线
|
|
this.line = this.draw.path()
|
|
this.line.opacity(0.5)
|
|
this.node.style.line(this.line)
|
|
// 同级位置占位符
|
|
this.placeholder = this.draw.rect().fill({
|
|
color: this.node.style.merge('lineColor', true)
|
|
})
|
|
this.mindMap.draw.add(this.clone)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* javascript comment
|
|
* @Author: 王林25
|
|
* @Date: 2021-11-23 19:35:16
|
|
* @Desc: 移除克隆节点
|
|
*/
|
|
removeCloneNode() {
|
|
if (!this.clone) {
|
|
return
|
|
}
|
|
this.clone.remove()
|
|
this.line.remove()
|
|
this.placeholder.remove()
|
|
}
|
|
|
|
/**
|
|
* javascript comment
|
|
* @Author: 王林25
|
|
* @Date: 2021-11-23 18:53:47
|
|
* @Desc: 拖动中
|
|
*/
|
|
onMove(x, y) {
|
|
if (!this.isMousedown) {
|
|
return;
|
|
}
|
|
this.createCloneNode()
|
|
let {
|
|
scaleX,
|
|
scaleY,
|
|
translateX,
|
|
translateY
|
|
} = this.drawTransform
|
|
this.cloneNodeLeft = x - this.offsetX
|
|
this.cloneNodeTop = y - this.offsetY
|
|
x = (this.cloneNodeLeft - translateX) / scaleX
|
|
y = (this.cloneNodeTop - translateY) / scaleY
|
|
let t = this.clone.transform()
|
|
this.clone.translate(x - t.translateX, y - t.translateY)
|
|
// 连接线
|
|
let parent = this.node.parent
|
|
this.line.plot(this.quadraticCurvePath(parent.left + parent.width / 2, parent.top + parent.height / 2, x + this.node.width / 2, y + this.node.height / 2))
|
|
this.checkOverlapNode()
|
|
}
|
|
|
|
/**
|
|
* @Author: 王林
|
|
* @Date: 2021-07-11 10:20:43
|
|
* @Desc: 检测重叠节点
|
|
*/
|
|
checkOverlapNode() {
|
|
if (!this.drawTransform) {
|
|
return
|
|
}
|
|
let {
|
|
scaleX,
|
|
scaleY,
|
|
translateX,
|
|
translateY
|
|
} = this.drawTransform
|
|
let checkRight = this.cloneNodeLeft + this.node.width * scaleX
|
|
let checkBottom = this.cloneNodeTop + this.node.height * scaleX
|
|
this.overlapNode = null
|
|
this.prevNode = null
|
|
this.nextNode = null
|
|
this.placeholder.size(0, 0)
|
|
bfsWalk(this.mindMap.renderer.root, (node) => {
|
|
if (node.nodeData.data.isActive) {
|
|
this.mindMap.renderer.setNodeActive(node, false)
|
|
}
|
|
if (node === this.node || this.node.isParent(node)) {
|
|
return
|
|
}
|
|
if (this.overlapNode || this.prevNode && this.nextNode) {
|
|
return
|
|
}
|
|
let {
|
|
left,
|
|
top,
|
|
width,
|
|
height
|
|
} = node
|
|
let _left = left
|
|
let _top = top
|
|
let _bottom = top + height
|
|
let right = (left + width) * scaleX + translateX
|
|
let bottom = (top + height) * scaleY + translateY
|
|
left = left * scaleX + translateX
|
|
top = top * scaleY + translateY
|
|
// 检测是否重叠
|
|
if (!this.overlapNode) {
|
|
if (
|
|
left <= checkRight && right >= this.cloneNodeLeft &&
|
|
top <= checkBottom && bottom >= this.cloneNodeTop
|
|
) {
|
|
this.overlapNode = node
|
|
}
|
|
}
|
|
// 检测兄弟节点位置
|
|
if (!this.prevNode && !this.nextNode && this.node.isBrother(node)) {
|
|
if (left <= checkRight && right >= this.cloneNodeLeft) {
|
|
if (this.cloneNodeTop > bottom && this.cloneNodeTop <= bottom + 10) {
|
|
this.prevNode = node
|
|
this.placeholder.size(node.width, 10).move(_left, _bottom)
|
|
} else if (checkBottom < top && checkBottom >= top - 10) {
|
|
this.nextNode = node
|
|
this.placeholder.size(node.width, 10).move(_left, _top - 10)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
if (this.overlapNode) {
|
|
this.mindMap.renderer.setNodeActive(this.overlapNode, true)
|
|
}
|
|
}
|
|
}
|
|
|
|
export default Drag |