Feat:节点增加鼠标滑过效果、节点激活效果重构、去除激活样式改变功能

This commit is contained in:
wanglin2 2023-08-27 22:10:49 +08:00
parent b35dd282ec
commit a24f7a73c8
7 changed files with 97 additions and 36 deletions

View File

@ -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()
}
}

View File

@ -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;
}
`

View File

@ -168,5 +168,7 @@ export const defaultOpt = {
// 开启鼠标双击复位思维导图位置及缩放
enableDblclickReset: true,
// 导出图片时canvas的缩放倍数该配置会和window.devicePixelRatio值取最大值
minExportImgCanvasScale: 2
minExportImgCanvasScale: 2,
// 节点鼠标hover和激活时显示的矩形边框颜色
hoverRectColor: 'rgb(94, 200, 248)'
}

View File

@ -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()
}
// 设置节点是否展开

View File

@ -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
}
// 获取数据

View File

@ -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

View File

@ -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