Feat:节点增加鼠标滑过效果、节点激活效果重构、去除激活样式改变功能
This commit is contained in:
parent
b35dd282ec
commit
a24f7a73c8
@ -11,7 +11,8 @@ import {
|
||||
layoutValueList,
|
||||
CONSTANTS,
|
||||
commonCaches,
|
||||
ERROR_TYPES
|
||||
ERROR_TYPES,
|
||||
cssContent
|
||||
} from './src/constants/constant'
|
||||
import { SVG } from '@svgdotjs/svg.js'
|
||||
import { simpleDeepClone, getType } from './src/utils'
|
||||
@ -37,6 +38,10 @@ class MindMap {
|
||||
this.height = this.elRect.height
|
||||
if (this.width <= 0 || this.height <= 0) throw new Error('容器元素el的宽高不能为0')
|
||||
|
||||
// 添加css
|
||||
this.cssEl = null
|
||||
this.addCss()
|
||||
|
||||
// 画布
|
||||
this.svg = SVG().addTo(this.el).size(this.width, this.height)
|
||||
this.draw = this.svg.group()
|
||||
@ -101,6 +106,19 @@ class MindMap {
|
||||
return opt
|
||||
}
|
||||
|
||||
// 添加css到页面
|
||||
addCss() {
|
||||
this.cssEl = document.createElement('style')
|
||||
this.cssEl.type = 'text/css'
|
||||
this.cssEl.innerHTML = cssContent
|
||||
document.head.appendChild(this.cssEl)
|
||||
}
|
||||
|
||||
// 移除css
|
||||
removeCss() {
|
||||
document.head.removeChild(this.cssEl)
|
||||
}
|
||||
|
||||
// 渲染,部分渲染
|
||||
render(callback, source = '') {
|
||||
this.batchExecution.push('render', () => {
|
||||
@ -419,6 +437,7 @@ class MindMap {
|
||||
Style.removeBackgroundStyle(this.el)
|
||||
this.el.innerHTML = ''
|
||||
this.el = null
|
||||
this.removeCss()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -348,4 +348,24 @@ export const ERROR_TYPES = {
|
||||
export const a4Size = {
|
||||
width: 592.28,
|
||||
height: 841.89
|
||||
}
|
||||
}
|
||||
|
||||
// css
|
||||
export const cssContent = `
|
||||
/* 鼠标hover和激活时渲染的矩形 */
|
||||
.smm-hover-node{
|
||||
display: none;
|
||||
opacity: 0.6;
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.smm-node:hover .smm-hover-node{
|
||||
display: block;
|
||||
}
|
||||
|
||||
.smm-node.active .smm-hover-node{
|
||||
display: block;
|
||||
opacity: 1;
|
||||
stroke-width: 2;
|
||||
}
|
||||
`
|
||||
@ -168,5 +168,7 @@ export const defaultOpt = {
|
||||
// 开启鼠标双击复位思维导图位置及缩放
|
||||
enableDblclickReset: true,
|
||||
// 导出图片时canvas的缩放倍数,该配置会和window.devicePixelRatio值取最大值
|
||||
minExportImgCanvasScale: 2
|
||||
minExportImgCanvasScale: 2,
|
||||
// 节点鼠标hover和激活时显示的矩形边框颜色
|
||||
hoverRectColor: 'rgb(94, 200, 248)'
|
||||
}
|
||||
|
||||
@ -407,7 +407,7 @@ class Render {
|
||||
// 激活节点需要显示展开收起按钮
|
||||
node.showExpandBtn()
|
||||
setTimeout(() => {
|
||||
node.updateNodeShape()
|
||||
node.updateNodeActive()
|
||||
}, 0)
|
||||
}
|
||||
},
|
||||
@ -1000,7 +1000,7 @@ class Render {
|
||||
} else {
|
||||
node.hideExpandBtn()
|
||||
}
|
||||
node.updateNodeShape()
|
||||
node.updateNodeActive()
|
||||
}
|
||||
|
||||
// 设置节点是否展开
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import Style from './Style'
|
||||
import Shape from './Shape'
|
||||
import { G, ForeignObject, SVG } from '@svgdotjs/svg.js'
|
||||
import { G, ForeignObject, SVG, Rect } from '@svgdotjs/svg.js'
|
||||
import nodeGeneralizationMethods from './nodeGeneralization'
|
||||
import nodeExpandBtnMethods from './nodeExpandBtn'
|
||||
import nodeCommandWrapsMethods from './nodeCommandWraps'
|
||||
@ -58,6 +58,7 @@ class Node {
|
||||
// 节点内容的容器
|
||||
this.group = null
|
||||
this.shapeNode = null // 节点形状节点
|
||||
this.hoverNode = null // 节点hover和激活的节点
|
||||
// 节点内容对象
|
||||
this._customNodeContent = null
|
||||
this._imgData = null
|
||||
@ -277,8 +278,8 @@ class Node {
|
||||
this.shapeNode = this.shapeInstance.createShape()
|
||||
this.shapeNode.addClass('smm-node-shape')
|
||||
this.shapeNode.translate(halfBorderWidth, halfBorderWidth)
|
||||
this.style.shape(this.shapeNode)
|
||||
this.group.add(this.shapeNode)
|
||||
this.updateNodeShape()
|
||||
// 渲染一个隐藏的矩形区域,用来触发展开收起按钮的显示
|
||||
this.renderExpandBtnPlaceholderRect()
|
||||
// 概要节点添加一个带所属节点id的类名
|
||||
@ -365,6 +366,11 @@ class Node {
|
||||
: 0)
|
||||
)
|
||||
this.group.add(textContentNested)
|
||||
// 激活hover和激活边框
|
||||
this.hoverNode = new Rect()
|
||||
this.hoverNode.addClass('smm-hover-node')
|
||||
this.style.hoverNode(this.hoverNode, width, height)
|
||||
this.group.add(this.hoverNode)
|
||||
}
|
||||
|
||||
// 给节点绑定事件
|
||||
@ -467,10 +473,11 @@ class Node {
|
||||
}
|
||||
|
||||
// 更新节点
|
||||
update(isLayout = false) {
|
||||
update() {
|
||||
if (!this.group) {
|
||||
return
|
||||
}
|
||||
this.updateNodeActive()
|
||||
let { alwaysShowExpandBtn } = this.mindMap.opt
|
||||
if (alwaysShowExpandBtn) {
|
||||
// 需要移除展开收缩按钮
|
||||
@ -543,13 +550,11 @@ class Node {
|
||||
return sizeChange
|
||||
}
|
||||
|
||||
// 更新节点形状样式
|
||||
updateNodeShape() {
|
||||
if (!this.shapeNode) return
|
||||
const shape = this.getShape()
|
||||
this.style[shape === CONSTANTS.SHAPE.RECTANGLE ? 'rect' : 'shape'](
|
||||
this.shapeNode
|
||||
)
|
||||
// 更新节点激活状态
|
||||
updateNodeActive() {
|
||||
if (!this.group) return
|
||||
const isActive = this.nodeData.data.isActive
|
||||
this.group[isActive ? 'addClass' : 'removeClass']('active')
|
||||
}
|
||||
|
||||
// 递归渲染
|
||||
@ -557,9 +562,7 @@ class Node {
|
||||
// 节点
|
||||
// 重新渲染连线
|
||||
this.renderLine()
|
||||
let isLayout = false
|
||||
if (!this.group) {
|
||||
isLayout = true
|
||||
// 创建组
|
||||
this.group = new G()
|
||||
this.group.addClass('smm-node')
|
||||
@ -569,7 +572,7 @@ class Node {
|
||||
this.bindGroupEvent()
|
||||
this.draw.add(this.group)
|
||||
this.layout()
|
||||
this.update(isLayout)
|
||||
this.update()
|
||||
} else {
|
||||
this.draw.add(this.group)
|
||||
if (this.needLayout) {
|
||||
@ -803,8 +806,8 @@ class Node {
|
||||
}
|
||||
|
||||
// 获取某个样式
|
||||
getStyle(prop, root, isActive) {
|
||||
let v = this.style.merge(prop, root, isActive)
|
||||
getStyle(prop, root) {
|
||||
let v = this.style.merge(prop, root)
|
||||
return v === undefined ? '' : v
|
||||
}
|
||||
|
||||
@ -833,7 +836,7 @@ class Node {
|
||||
|
||||
// 获取节点非节点状态的边框大小
|
||||
getBorderWidth() {
|
||||
return this.style.merge('borderWidth', false, false) || 0
|
||||
return this.style.merge('borderWidth', false) || 0
|
||||
}
|
||||
|
||||
// 获取数据
|
||||
|
||||
@ -69,7 +69,8 @@ export default class Shape {
|
||||
let node = null
|
||||
// 矩形
|
||||
if (shape === CONSTANTS.SHAPE.RECTANGLE) {
|
||||
node = new Rect().size(width, height)
|
||||
// node = new Rect().size(width, height)
|
||||
node = this.createRect()
|
||||
} else if (shape === CONSTANTS.SHAPE.DIAMOND) {
|
||||
// 菱形
|
||||
node = this.createDiamond()
|
||||
@ -98,6 +99,19 @@ export default class Shape {
|
||||
return node
|
||||
}
|
||||
|
||||
// 创建矩形TODO
|
||||
createRect() {
|
||||
let { width, height } = this.node
|
||||
let borderRadius = this.node.style.merge('borderRadius')
|
||||
return new Path().plot(`
|
||||
M${0},0
|
||||
L${width},0
|
||||
L${width},${height}
|
||||
L${0},${height}
|
||||
L${0},${0}
|
||||
`)
|
||||
}
|
||||
|
||||
// 创建菱形
|
||||
createDiamond() {
|
||||
let { width, height } = this.node
|
||||
|
||||
@ -42,7 +42,7 @@ class Style {
|
||||
}
|
||||
|
||||
// 合并样式
|
||||
merge(prop, root, isActive) {
|
||||
merge(prop, root) {
|
||||
let themeConfig = this.ctx.mindMap.themeConfig
|
||||
// 三级及以下节点
|
||||
let defaultConfig = themeConfig.node
|
||||
@ -59,17 +59,6 @@ class Style {
|
||||
// 二级节点
|
||||
defaultConfig = themeConfig.second
|
||||
}
|
||||
// 激活状态
|
||||
if (isActive !== undefined ? isActive : this.ctx.nodeData.data.isActive) {
|
||||
if (
|
||||
this.ctx.nodeData.data.activeStyle &&
|
||||
this.ctx.nodeData.data.activeStyle[prop] !== undefined
|
||||
) {
|
||||
return this.ctx.nodeData.data.activeStyle[prop]
|
||||
} else if (defaultConfig.active && defaultConfig.active[prop]) {
|
||||
return defaultConfig.active[prop]
|
||||
}
|
||||
}
|
||||
// 优先使用节点本身的样式
|
||||
return this.getSelfStyle(prop) !== undefined
|
||||
? this.getSelfStyle(prop)
|
||||
@ -77,8 +66,8 @@ class Style {
|
||||
}
|
||||
|
||||
// 获取某个样式值
|
||||
getStyle(prop, root, isActive) {
|
||||
return this.merge(prop, root, isActive)
|
||||
getStyle(prop, root) {
|
||||
return this.merge(prop, root)
|
||||
}
|
||||
|
||||
// 获取自身自定义样式
|
||||
@ -220,6 +209,20 @@ class Style {
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
// hover和激活节点
|
||||
hoverNode(node, width, height) {
|
||||
const { hoverRectColor } = this.ctx.mindMap.opt
|
||||
node
|
||||
.size(width + 0, height + 0)
|
||||
.x(-0)
|
||||
.y(-0)
|
||||
.radius(5)
|
||||
.fill('none')
|
||||
.stroke({
|
||||
color: hoverRectColor
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Style.cacheStyle = null
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user