如何实现AI生成节点内容
目前AI能力非常流行,每个应用都给自己加上了AI的能力提高竞争力,那么在使用了simple-mind-map
的情况下如何添加AI的能力呢,本教程会详细的教你如何实现。
首先要说明的是本教程并不会真的实现一个可用的AI能力,只是在假设你要实现该功能的前提下来教你如何调用对应的API来实现你想要的效果。
其次AI返回的数据结构不尽相同,你都需要自行转换成simple-mind-map
的结构类型。
自动生成整个思维导图
一次生成
通过AI生成整个思维导图并且一次直接生成,这个其实就是普通的回显功能,那么你可以在实例化时通过data
传入生成的数据:
const mindMap = new MindMap({
el,
data: {
data: {
text: '我是自动生成的节点'
},
children: [
{
data: {
text: '子节点'
},
children: []
}
]
}
})
也可以在实例化之后使用setData
方法设置:
mindMap.setData({
data: {
text: '我是自动生成的节点'
},
children: [
{
data: {
text: '子节点'
},
children: []
}
]
})
依次生成节点
如果你想像ChatGPT一样依次生成节点,那么推荐使用updateData
方法增量更新节点数据,而不是手动获取到之前插入的节点实例,再调用命令来插入下级节点,这样会复杂很多,当然,如果你能轻松的知道当前创建到哪里了,并且下一个节点在哪个节点下创建,可以忽略。
updateData方法是v0.9.9+的方法,之前的版本可以使用下面的方法:
const updateData = (data) => {
mindMap.renderer.setData(data)
mindMap.render()
mindMap.command.addHistory()
}
增量更新的前提是之前生成的节点都存在uid
,并且不会变化,这样调用updateData
方法渲染时会根据uid
来复用之前的节点,只创建新的节点,达到依次生成的目的。
比如第一次返回的数据:
const data = {
data: {
text: '根节点',
uid: '1'
},
children: []
}
mindMap.setData(data)
第二次返回的数据:
const data = {
data: {
text: '根节点',
uid: '1'
},
children: [
{
data: {
text: '二级节点',
uid: '2'
},
children: []
}
]
}
mindMap.updateData(data)
以此类推,这样虽然是整个数据更新,但是因为复用的原因画布呈现的是依次生成新节点的效果。
当生成的节点多了会有个问题,就是新生成的节点在画布外看不见了,所以我们要将新生成的节点移动到画布中心,首先可以监听data_change_detail
事件来获取到详细的更新数据,找出其中新创建的节点数据,然后使用findNodeByUid
方法找出对应的节点实例,最后调用moveNodeToCenter
方法将该节点移动到画布中心即可。
mindMap.on('data_change_detail', (list) => {
// 找出新创建节点中的最后一个
const lastCreate = list.filter((item) => {
return item.action === 'create'
})[0]
if (lastCreate) {
const uid = lastCreate.data.data.uid
const node = mindMap.renderer.findNodeByUid(uid)
if (node) {
mindMap.renderer.moveNodeToCenter(node)
}
}
})
当节点数据多了,可能data_change_detail
事件触发时节点树还没渲染完毕,导致获取不到节点,解决这个问题可以通过监听node_tree_render_end
事件:
let waitUid = ''
mindMap.on('data_change_detail', (list) => {
// ...
if (lastCreate) {
// ...
if (node) {
mindMap.renderer.moveNodeToCenter(node)
} else {
waitUid = uid
}
}
})
mindMap.on('node_tree_render_end', () =>{
if (waitUid) {
waitUid = ''
const node = mindMap.renderer.findNodeByUid(waitUid)
if (node) {
mindMap.renderer.moveNodeToCenter(node)
}
}
})
当在data_change_detail
事件中没有获取到节点实例就将该uid
保存起来,然后在node_tree_render_end
事件里判断是否有保存的uid
,是的话就获取该节点实例并移动到画布中心。
最后,当自动生成节点中最好禁止用户操作,否则可能会产生异常。
完整示例
在某个节点下自动生成新节点
在某个节点下自动生成新节点,如果也要依次生成,那么可以使用前面的增量更新数据的方式。如果一次生成,那么可以简单的调用插入新节点的命令即可。
一次生成下级节点
// 插入一个子节点
mindMap.execCommand('INSERT_CHILD_NODE',
false,
node,
{
data: {
text: '三级节点'
},
children: []
},
[
{
data: {
text: '三级节点的子节点'
},
children: []
}
]
)
// 插入多个子节点
mindMap.execCommand('INSERT_MULTI_CHILD_NODE', node, [
{
data: {
text: '三级节点'
},
children: []
},
{
data: {
text: '三级节点'
},
children: []
}
])
一次生成兄弟节点
// 插入一个兄弟节点
mindMap.execCommand('INSERT_NODE',
false,
node,
{
data: {
text: '二级节点'
},
children: []
},
[
{
data: {
text: '二级节点的子节点'
},
children: []
}
]
)
// 插入多个兄弟节点
mindMap.execCommand('INSERT_MULTI_NODE', node, [
{
data: {
text: '二级节点'
},
children: []
},
{
data: {
text: '二级节点'
},
children: []
}
])
这样新创建的节点默认会被激活但不进入编辑,如果你连激活都不想要的话,那么可以通过将实例化选项createNewNodeBehavior
设置为notActive
。
当自动生成结束后你又想恢复创建新节点时自动进入编辑状态,那么可以通过updateConfig
方法修改createNewNodeBehavior
:
mindMap.updateConfig({
createNewNodeBehavior: 'default'
})