Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

优化大量节点时卡顿问题。主要是通过减少布局循环、仅处理变动节点和连接线只画可见区域得线来解决。增加shift多选功能。 #1073

Open
wants to merge 2 commits into
base: feature
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions simple-mind-map/src/constants/constant.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
export const CONSTANTS = {
CHANGE_THEME: 'changeTheme',
CHANGE_LAYOUT: 'changeLayout',
HISTORY_RECORD:'historyRecord',
SET_DATA: 'setData',
MODE: {
READONLY: 'readonly',
Expand Down
33 changes: 32 additions & 1 deletion simple-mind-map/src/core/render/Render.js
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,8 @@ class Render {
const data = this.mindMap.command[type](step)
if (data) {
this.renderTree = data
this.mindMap.render()
// 给前进后退增加类型 主要是当它这样操作时全量渲染 暂时未作两次数据得变更比对 这个是简单临时方案
this.mindMap.render(()=>{},CONSTANTS.HISTORY_RECORD)
}
this.mindMap.emit('data_change', data)
}
Expand Down Expand Up @@ -987,7 +988,12 @@ class Render {
const parent = node.parent
// 获取当前节点所在位置
const index = getNodeDataIndex(node)
//这里主要是 节点还未创建 只能记录下创建在父节点的位置等创建好了再添加
newNode.data.parentIndex = index
parent.nodeData.children.splice(index, 1, newNode)
//这里主要是 节点还未创建 只能清空父节点然后记录下父节点的uid等创建好了替换
node.parent = null;
node.parentUid = newNode.data.uid
})
// 如果同时对多个节点插入子节点,需要清除原来激活的节点
if (focusNewNode) {
Expand Down Expand Up @@ -1330,6 +1336,10 @@ class Render {
// 目标节点
let existParent = exist.parent
let existBorthers = existParent.children
item.layerIndex =exist.layerIndex
item.parent =exist.parent
item.getSize()
item.needLayout = true
let existIndex = getNodeIndexInNodeList(exist, existBorthers)
if (existIndex === -1) {
return
Expand Down Expand Up @@ -1432,6 +1442,22 @@ class Render {
} else {
const parent = node.parent
const index = getNodeDataIndex(node)
const children = node.children || [];
// 对子节点实例也操作
children.forEach((item)=>{
item.layerIndex =node.layerIndex
item.parent =node.parent
if(item.layerIndex === 1){
// 如果删除父节点后自己点变成1级节点 重新计算样式
item.getSize()
item.needLayout = true
}
})
parent.children.splice(
index,
1,
...children
)
parent.nodeData.children.splice(
index,
1,
Expand Down Expand Up @@ -1526,11 +1552,16 @@ class Render {
return !item.isRoot
})
nodeList.forEach(item => {
item.layerIndex = toNode.layerIndex + 1
this.removeNodeFromActiveList(item)
removeFromParentNodeData(item)
toNode.setData({
expand: true
})
item.parent = toNode
item.getSize()
item.needLayout = true
toNode.children.push(item)
toNode.nodeData.children.push(item.nodeData)
})
this.emitNodeActiveEvent()
Expand Down
67 changes: 61 additions & 6 deletions simple-mind-map/src/core/render/node/MindMapNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,11 @@ class MindMapNode {
this.updateGeneralization()
this.initDragHandle()
}

//子节点中是否包含这个节点
isHaveNode(node){
const children = this.children
return children.includes(node)
}
// 支持自定义位置
get left() {
return this.customLeft || this._left
Expand Down Expand Up @@ -688,6 +692,41 @@ class MindMapNode {
](this, true)
this.renderer.emitNodeActiveEvent(isActive ? null : this)
}
// 使用shift键进行多选和取消多选
if (!readonly && e.shiftKey && enableCtrlKeyNodeSelection) {
this.isMultipleChoice = true
let isActive = this.getData('isActive')
if (!isActive){
const activeNodeList = this.renderer.activeNodeList
if(activeNodeList.length){
const children = this.parent.children
const currentIndex = children.indexOf(this)
let max = currentIndex
let min = currentIndex
let isAllChildren = true
for (let i = 0; i < activeNodeList.length; i++) {
let item = activeNodeList[i]
const ind = children.indexOf(item)
if(ind < 0){
isAllChildren = false
break;
} else{
ind >= max ? max = ind : null
min >= ind ? min = ind : null
}
}
if(isAllChildren){
let c = this.parent.children.slice(min,max+1)
c.forEach(child => {
this.mindMap.renderer[
'addNodeToActiveList'
](child, true)
this.renderer.emitNodeActiveEvent(child)
})
}
}
}
}
this.mindMap.emit('node_mousedown', this, e)
})
this.group.on('mouseup', e => {
Expand Down Expand Up @@ -748,8 +787,11 @@ class MindMapNode {
if (
!(this.getData('isActive') && this.renderer.activeNodeList.length === 1)
) {
this.renderer.clearActiveNodeList()
this.active(e)
// 多选的时候 右键在已选中的节点上时 不取消其它节点的选中状态
if(!this.getData('isActive')){
this.renderer.clearActiveNodeList()
this.active(e)
}
}
this.mindMap.emit('node_contextmenu', e, this)
})
Expand Down Expand Up @@ -873,14 +915,23 @@ class MindMapNode {
this.updateDragHandle()
}
}

// 渲染父节点的连接线 只有不可见得父节点才会去渲染 这样可以做到当只渲染可见连线时 出现单个节点没有连接父节点得情况
renderParentLine(node,performanceConfig){
const parNode = node.parent
if(!parNode) return
const isInClient = parNode.checkIsInClient(performanceConfig.padding)
//如果父节点可见 就不继续遍历
if(isInClient) return
parNode.renderLine()
this.renderParentLine(parNode,performanceConfig)
}
// 递归渲染
// forceRender:强制渲染,无论是否处于画布可视区域
// async:异步渲染
render(callback = () => {}, forceRender = false, async = false) {
// 节点
// 重新渲染连线
this.renderLine()
// 不在全量渲染
//this.renderLine()
const { openPerformance, performanceConfig } = this.mindMap.opt
// 强制渲染、或没有开启性能模式、或不在画布可视区域内不渲染节点内容
// 根节点不进行懒加载,始终渲染,因为滚动条插件依赖根节点进行计算
Expand All @@ -890,6 +941,10 @@ class MindMapNode {
this.checkIsInClient(performanceConfig.padding) ||
this.isRoot
) {
//给不可见的父节点画线 防止出现单独的节点没有连线问题
this.renderParentLine(this,performanceConfig)
//只给屏幕内的节点画线
this.renderLine()
if (!this.group) {
// 创建组
this.group = new G()
Expand Down
40 changes: 34 additions & 6 deletions simple-mind-map/src/layouts/Base.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ class Base {
}

// 创建节点实例
createNode(data, parent, isRoot, layerIndex, index, ancestors) {
// 增加参数isNotReset,本质是不想让节点reset 但是目前只改了 logicalStructure结构的代码 为了不影响其它结构代码增加此参数做判断
createNode(data, parent, isRoot, layerIndex, index, ancestors,isNotReset) {
// 创建节点
// 库前置内容数据
const nodeInnerPrefixData = {}
Expand All @@ -105,12 +106,21 @@ class Base {
newNode.layerIndex,
layerIndex
)
newNode.reset()
// 不再重置节点 节点的子节点添加 删除等 分别再对应的操作里处理 这样可以做到只针对修改节点进行处理而不是全量处理
if(!isNotReset){
newNode.reset()
}
newNode.layerIndex = layerIndex
if (isRoot) {
newNode.isRoot = true
} else {
newNode.parent = parent._node
// 这里是只增加父级节点时 操作代码 只进行了数据上的添加父节点 而还没实际创建父节点所以记录父节点UId
// 因为遍历从上而下所以此时父节点是肯定创建好的。所以此时可正常将父节点实例给赋值。
if(!newNode.parentUid){
newNode.parent = parent._node
}else{
newNode.parent = this.renderer.nodeCache[newNode.parentUid]
}
}
this.cacheNode(data._node.uid, newNode)
this.checkIsLayoutChangeRerenderExpandBtnPlaceholderRect(newNode)
Expand Down Expand Up @@ -160,13 +170,22 @@ class Base {
newNode.layerIndex,
layerIndex
)
newNode.reset()
// 不再重置节点 节点的子节点添加 删除等 分别再对应的操作里处理 这样可以做到只针对修改节点进行处理而不是全量处理
if(!isNotReset){
newNode.reset()
}
newNode.nodeData = newNode.handleData(data || {})
newNode.layerIndex = layerIndex
if (isRoot) {
newNode.isRoot = true
} else {
newNode.parent = parent._node
// 这里是只增加父级节点时 操作代码 只进行了数据上的添加父节点 而还没实际创建父节点所以记录父节点UId
// 因为遍历从上而下所以此时父节点是肯定创建好的。所以此时可正常将父节点实例给赋值。
if(!newNode.parentUid){
newNode.parent = parent._node
}else{
newNode.parent = this.renderer.nodeCache[newNode.parentUid]
}
}
this.cacheNode(uid, newNode)
this.checkIsLayoutChangeRerenderExpandBtnPlaceholderRect(newNode)
Expand Down Expand Up @@ -233,7 +252,16 @@ class Base {
this.root = newNode
} else {
// 互相收集
parent._node.addChildren(newNode)
if( !parent._node.isHaveNode(newNode)){
// 因为插入父级节点的时候还没创建节点还没创建号所以记录下要插入的父节点位置 创建好的时候再插入
// 这里同子节点关联父节点一样都是因为插入父节点的特殊性导致单独处理
const parentIndex = data.data.parentIndex
if(parentIndex || parentIndex === 0){
parent._node.children.splice(parentIndex, 1, newNode)
}else{
parent._node.addChildren(newNode)
}
}
}
return newNode
}
Expand Down
Loading