mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-17 14:04:47 +08:00
Feat:1.演示模式中禁止画布的所有内容响应鼠标事件;2.节点的超链接和备注图标支持响应鼠标事件;3.支持填空模式
This commit is contained in:
@@ -128,13 +128,18 @@ class MindMap {
|
||||
// 创建容器元素
|
||||
initContainer() {
|
||||
const { associativeLineIsAlwaysAboveNode } = this.opt
|
||||
// 给容器元素添加一个类名
|
||||
this.el.classList.add('smm-mind-map-container')
|
||||
// 节点关联线容器
|
||||
const createAssociativeLineDraw = () => {
|
||||
this.associativeLineDraw = this.draw.group()
|
||||
this.associativeLineDraw.addClass('smm-associative-line-container')
|
||||
}
|
||||
// 画布
|
||||
this.svg = SVG().addTo(this.el).size(this.width, this.height)
|
||||
this.svg = SVG()
|
||||
.addTo(this.el)
|
||||
.size(this.width, this.height)
|
||||
|
||||
// 容器
|
||||
this.draw = this.svg.group()
|
||||
this.draw.addClass('smm-container')
|
||||
@@ -432,7 +437,13 @@ class MindMap {
|
||||
// 需要裁减的区域
|
||||
let clipData = null
|
||||
if (node) {
|
||||
clipData = getNodeTreeBoundingRect(node, rect.x, rect.y, paddingX, paddingY)
|
||||
clipData = getNodeTreeBoundingRect(
|
||||
node,
|
||||
rect.x,
|
||||
rect.y,
|
||||
paddingX,
|
||||
paddingY
|
||||
)
|
||||
}
|
||||
// 内边距
|
||||
const fixHeight = 0
|
||||
@@ -581,6 +592,8 @@ class MindMap {
|
||||
this.svg.remove()
|
||||
// 去除给容器元素设置的背景样式
|
||||
Style.removeBackgroundStyle(this.el)
|
||||
// 移除给容器元素添加的类名
|
||||
this.el.classList.remove('smm-mind-map-container')
|
||||
this.el.innerHTML = ''
|
||||
this.el = null
|
||||
this.removeCss()
|
||||
|
||||
@@ -316,7 +316,10 @@ function createNoteNode() {
|
||||
return null
|
||||
}
|
||||
let iconSize = this.mindMap.themeConfig.iconSize
|
||||
let node = new SVG().attr('cursor', 'pointer').size(iconSize, iconSize)
|
||||
let node = new SVG()
|
||||
.attr('cursor', 'pointer')
|
||||
.addClass('smm-node-note')
|
||||
.size(iconSize, iconSize)
|
||||
// 透明的层,用来作为鼠标区域
|
||||
node.add(new Rect().size(iconSize, iconSize).fill({ color: 'transparent' }))
|
||||
// 备注图标
|
||||
|
||||
@@ -14,16 +14,25 @@ const defaultConfig = {
|
||||
transition: 'all 0.3s ease-out', // 高亮框动画的过渡
|
||||
zIndex: 9999, // 高亮框元素的层级
|
||||
padding: 20, // 高亮框的内边距
|
||||
margin: 50 // 高亮框的外边距
|
||||
margin: 50, // 高亮框的外边距
|
||||
openBlankMode: true // 是否开启填空模式,即带下划线的文本默认不显示,按回车键才依次显示
|
||||
}
|
||||
|
||||
// 演示插件
|
||||
class Demonstrate {
|
||||
constructor(opt) {
|
||||
this.mindMap = opt.mindMap
|
||||
// 演示的步骤列表
|
||||
this.stepList = []
|
||||
// 当前所在步骤
|
||||
this.currentStepIndex = 0
|
||||
this.maskEl = null
|
||||
// 当前所在步骤对应的节点实例
|
||||
this.currentStepNode = null
|
||||
// 当前所在步骤节点的下划线文本数据
|
||||
this.currentUnderlineTextData = null
|
||||
// 临时的样式剩余
|
||||
this.tmpStyleEl = null
|
||||
// 高亮样式元素
|
||||
this.highlightEl = null
|
||||
this.transformState = null
|
||||
this.renderTree = null
|
||||
@@ -47,6 +56,8 @@ class Demonstrate {
|
||||
}
|
||||
|
||||
_enter() {
|
||||
// 添加演示用的临时的样式
|
||||
this.addTmpStyles()
|
||||
// 记录演示前的画布状态
|
||||
this.transformState = this.mindMap.view.getTransformData()
|
||||
// 记录演示前的画布数据
|
||||
@@ -79,27 +90,53 @@ class Demonstrate {
|
||||
this.transformState = null
|
||||
this.stepList = []
|
||||
this.currentStepIndex = 0
|
||||
this.currentStepNode = null
|
||||
this.currentUnderlineTextData = null
|
||||
this.unBindEvent()
|
||||
this.removeTmpStyles()
|
||||
this.removeHighlightEl()
|
||||
this.mindMap.command.recovery()
|
||||
this.mindMap.keyCommand.recovery()
|
||||
this.mindMap.emit('exit_demonstrate')
|
||||
}
|
||||
|
||||
// 添加临时的样式
|
||||
addTmpStyles() {
|
||||
this.tmpStyleEl = document.createElement('style')
|
||||
let cssText = `
|
||||
/* 画布所有元素禁止响应鼠标事件 */
|
||||
.smm-mind-map-container {
|
||||
pointer-events: none;
|
||||
}
|
||||
/* 超链接图标允许响应鼠标事件 */
|
||||
.smm-node a {
|
||||
pointer-events: all;
|
||||
}
|
||||
/* 备注图标允许响应鼠标事件 */
|
||||
.smm-node .smm-node-note {
|
||||
pointer-events: all;
|
||||
}
|
||||
`
|
||||
if (this.config.openBlankMode) {
|
||||
cssText += `
|
||||
/* 带下划线的文本内容全部隐藏 */
|
||||
.smm-richtext-node-wrap u {
|
||||
opacity: 0;
|
||||
}
|
||||
`
|
||||
}
|
||||
this.tmpStyleEl.innerText = cssText
|
||||
document.head.appendChild(this.tmpStyleEl)
|
||||
}
|
||||
|
||||
// 移除临时的样式
|
||||
removeTmpStyles() {
|
||||
if (this.tmpStyleEl) document.head.removeChild(this.tmpStyleEl)
|
||||
}
|
||||
|
||||
// 创建高亮元素
|
||||
createHighlightEl() {
|
||||
if (!this.highlightEl) {
|
||||
// 遮罩元素
|
||||
this.maskEl = document.createElement('div')
|
||||
this.maskEl.style.cssText = `
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: ${this.config.zIndex};
|
||||
`
|
||||
this.mindMap.el.appendChild(this.maskEl)
|
||||
// 高亮元素
|
||||
this.highlightEl = document.createElement('div')
|
||||
this.highlightEl.style.cssText = `
|
||||
@@ -108,6 +145,7 @@ class Demonstrate {
|
||||
border-radius: ${this.config.borderRadius};
|
||||
transition: ${this.config.transition};
|
||||
z-index: ${this.config.zIndex + 1};
|
||||
pointer-events: none;
|
||||
`
|
||||
this.mindMap.el.appendChild(this.highlightEl)
|
||||
}
|
||||
@@ -119,10 +157,6 @@ class Demonstrate {
|
||||
this.mindMap.el.removeChild(this.highlightEl)
|
||||
this.highlightEl = null
|
||||
}
|
||||
if (this.maskEl) {
|
||||
this.mindMap.el.removeChild(this.maskEl)
|
||||
this.maskEl = null
|
||||
}
|
||||
}
|
||||
|
||||
// 更新高亮元素的位置和大小
|
||||
@@ -180,6 +214,9 @@ class Demonstrate {
|
||||
} else if (e.keyCode === keyMap.Esc) {
|
||||
// 退出演示
|
||||
this.exit()
|
||||
} else if (e.keyCode === keyMap.Enter) {
|
||||
// 回车键显示隐藏的下划线文本
|
||||
this.showNextUnderlineText()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,8 +235,31 @@ class Demonstrate {
|
||||
}
|
||||
}
|
||||
|
||||
// 显示隐藏的下划线文本
|
||||
showNextUnderlineText() {
|
||||
if (
|
||||
!this.config.openBlankMode ||
|
||||
!this.currentStepNode ||
|
||||
!this.currentUnderlineTextData
|
||||
)
|
||||
return
|
||||
const { index, list, length } = this.currentUnderlineTextData
|
||||
if (index >= length) return
|
||||
const node = list[index]
|
||||
this.currentUnderlineTextData.index++
|
||||
node.node.style.opacity = 1
|
||||
}
|
||||
|
||||
// 跳转到某一张
|
||||
jump(index) {
|
||||
// 移除该当前下划线元素设置的样式
|
||||
if (this.currentUnderlineTextData) {
|
||||
this.currentUnderlineTextData.list.forEach(item => {
|
||||
item.node.style.opacity = ''
|
||||
})
|
||||
this.currentUnderlineTextData = null
|
||||
}
|
||||
this.currentStepNode = null
|
||||
this.currentStepIndex = index
|
||||
this.mindMap.emit(
|
||||
'demonstrate_jump',
|
||||
@@ -226,6 +286,16 @@ class Demonstrate {
|
||||
}
|
||||
// 1.聚焦到某个节点
|
||||
if (step.type === 'node') {
|
||||
this.currentStepNode = node
|
||||
// 当前节点存在带下划线的文本内容
|
||||
const uNodeList = this.config.openBlankMode ? node.group.find('u') : null
|
||||
if (uNodeList && uNodeList.length > 0) {
|
||||
this.currentUnderlineTextData = {
|
||||
index: 0,
|
||||
list: uNodeList,
|
||||
length: uNodeList.length
|
||||
}
|
||||
}
|
||||
// 适应画布大小
|
||||
this.mindMap.view.fit(
|
||||
() => {
|
||||
|
||||
@@ -139,6 +139,7 @@ export default {
|
||||
top: 20px;
|
||||
cursor: pointer;
|
||||
z-index: 10001;
|
||||
pointer-events: all;
|
||||
|
||||
.icon {
|
||||
font-size: 28px;
|
||||
@@ -150,6 +151,7 @@ export default {
|
||||
position: absolute;
|
||||
right: 40px;
|
||||
bottom: 20px;
|
||||
pointer-events: all;
|
||||
|
||||
z-index: 10001;
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user