Feat:新增将思维导图图形限制在画布内的配置选项

This commit is contained in:
街角小林
2023-12-21 11:24:24 +08:00
parent 4d9aa1d3c2
commit 3d0b257325
3 changed files with 107 additions and 10 deletions

View File

@@ -238,5 +238,8 @@ export const defaultOpt = {
*/
createNewNodeBehavior: CONSTANTS.CREATE_NEW_NODE_BEHAVIOR.DEFAULT,
// 当节点图片加载失败时显示的默认图片
defaultNodeImage: ''
defaultNodeImage: '',
// 是否将思维导图限制在画布内
// 比如向右拖动时,思维导图图形的最左侧到达画布中心时将无法继续向右拖动,其他同理
isLimitMindMapInCanvas: false
}

View File

@@ -194,6 +194,7 @@ class View {
// 应用变换
transform() {
this.limitMindMapInCanvas()
this.mindMap.draw.transform({
origin: [0, 0],
scale: this.scale,
@@ -306,6 +307,64 @@ class View {
}
this.translateXY(newX, newY)
}
// 将思维导图限制在画布内
limitMindMapInCanvas() {
if (!this.mindMap.opt.isLimitMindMapInCanvas) return
let { scale, left, top, right, bottom } = this.getPositionLimit()
// 如果缩放值改变了
const scaleRatio = this.scale / scale
left *= scaleRatio
right *= scaleRatio
top *= scaleRatio
bottom *= scaleRatio
// 加上画布中心点距离
const centerX = this.mindMap.width / 2
const centerY = this.mindMap.height / 2
const scaleOffset = this.scale - 1
left -= scaleOffset * centerX
right -= scaleOffset * centerX
top -= scaleOffset * centerY
bottom -= scaleOffset * centerY
// 判断是否超出边界
if (this.x > left) {
this.x = left
}
if (this.x < right) {
this.x = right
}
if (this.y > top) {
this.y = top
}
if (this.y < bottom) {
this.y = bottom
}
}
// 计算图形四个方向的位置边界值
getPositionLimit() {
const { scaleX, scaleY } = this.mindMap.draw.transform()
const drawRect = this.mindMap.draw.rbox()
const rootRect = this.mindMap.renderer.root.group.rbox()
const rootCenterOffset = this.mindMap.renderer.layout.getRootCenterOffset(
rootRect.width,
rootRect.height
)
const left = rootRect.x - drawRect.x - rootCenterOffset.x * scaleX
const right = rootRect.x - drawRect.x2 - rootCenterOffset.x * scaleX
const top = rootRect.y - drawRect.y - rootCenterOffset.y * scaleY
const bottom = rootRect.y - drawRect.y2 - rootCenterOffset.y * scaleY
return {
scale: scaleX,
left,
right,
top,
bottom
}
}
}
export default View

View File

@@ -168,18 +168,21 @@ class Base {
}
}
// 规范initRootNodePosition配置
formatInitRootNodePosition(pos) {
const { CENTER } = CONSTANTS.INIT_ROOT_NODE_POSITION
if (!pos || !Array.isArray(pos) || pos.length < 2) {
pos = [CENTER, CENTER]
}
return pos
}
// 定位节点到画布中间
setNodeCenter(node, position) {
let { initRootNodePosition } = this.mindMap.opt
initRootNodePosition = position || initRootNodePosition
let { CENTER } = CONSTANTS.INIT_ROOT_NODE_POSITION
if (
!initRootNodePosition ||
!Array.isArray(initRootNodePosition) ||
initRootNodePosition.length < 2
) {
initRootNodePosition = [CENTER, CENTER]
}
initRootNodePosition = this.formatInitRootNodePosition(
position || initRootNodePosition
)
node.left = this.formatPosition(
initRootNodePosition[0],
this.mindMap.width,
@@ -192,6 +195,38 @@ class Base {
)
}
// 当initRootNodePosition配置不为默认的['center','center']时,计算当前配置和默认配置情况下,中心点位置的差值
getRootCenterOffset(width, height) {
// 如果initRootNodePosition是默认的那么不需要计算
let { initRootNodePosition } = this.mindMap.opt
const { CENTER } = CONSTANTS.INIT_ROOT_NODE_POSITION
initRootNodePosition = this.formatInitRootNodePosition(initRootNodePosition)
if (
initRootNodePosition[0] === CENTER &&
initRootNodePosition[1] === CENTER
) {
return {
x: 0,
y: 0
}
}
// 否则需要计算当前配置和默认配置的差值
const tmpNode = {
width: width,
height: height
}
const tmpNode2 = {
width: width,
height: height
}
this.setNodeCenter(tmpNode, ['center', 'center'])
this.setNodeCenter(tmpNode2)
return {
x: tmpNode2.left - tmpNode.left,
y: tmpNode2.top - tmpNode.top
}
}
// 更新子节点属性
updateChildren(children, prop, offset) {
children.forEach(item => {