Feat:格式刷支持刷节点所有生效的样式,包括来自主题的和自定义的

This commit is contained in:
街角小林
2024-08-29 10:30:52 +08:00
parent 89d89f4dd8
commit 4e327c3a48
4 changed files with 117 additions and 36 deletions

View File

@@ -409,5 +409,9 @@ export const defaultOpt = {
// 【OuterFrame】插件
outerFramePaddingX: 10,
outerFramePaddingY: 10
outerFramePaddingY: 10,
// 【Painter】插件
// 是否只格式刷节点手动设置的样式,不考虑节点通过主题的应用的样式
onlyPainterNodeCustomStyles: false
}

View File

@@ -34,6 +34,8 @@ class MindMapNode {
this.lineDraw = this.mindMap.lineDraw
// 样式实例
this.style = new Style(this)
// 节点当前生效的全部样式
this.effectiveStyles = {}
// 形状实例
this.shapeInstance = new Shape(this)
this.shapePadding = {

View File

@@ -85,7 +85,14 @@ class Style {
// 获取某个样式值
getStyle(prop, root) {
return this.merge(prop, root)
const value = this.merge(prop, root)
if (!root) {
const styles = {
[prop]: value
}
this.addToEffectiveStyles(styles)
}
return value
}
// 获取自身自定义样式
@@ -93,26 +100,47 @@ class Style {
return this.ctx.getData(prop)
}
// 更新当前节点生效的样式数据
addToEffectiveStyles(styles) {
this.ctx.effectiveStyles = {
...this.ctx.effectiveStyles,
...styles
}
}
// 矩形
rect(node) {
this.shape(node)
node.radius(this.merge('borderRadius'))
const styles = {
borderRadius: this.merge('borderRadius')
}
this.addToEffectiveStyles(styles)
node.radius(styles.borderRadius)
}
// 形状
shape(node) {
if (this.merge('gradientStyle')) {
const styles = {
gradientStyle: this.merge('gradientStyle'),
startColor: this.merge('startColor'),
endColor: this.merge('endColor'),
fillColor: this.merge('fillColor'),
borderColor: this.merge('borderColor'),
borderWidth: this.merge('borderWidth'),
borderDasharray: this.merge('borderDasharray')
}
if (styles.gradientStyle) {
if (!this._gradient) {
this._gradient = this.ctx.nodeDraw.gradient('linear')
}
this._gradient.update(add => {
add.stop(0, this.merge('startColor'))
add.stop(1, this.merge('endColor'))
add.stop(0, styles.startColor)
add.stop(1, styles.endColor)
})
node.fill(this._gradient)
} else {
node.fill({
color: this.merge('fillColor')
color: styles.fillColor
})
}
// 节点使用横线样式,不需要渲染非激活状态的边框样式
@@ -125,56 +153,94 @@ class Style {
// return
// }
node.stroke({
color: this.merge('borderColor'),
width: this.merge('borderWidth'),
dasharray: this.merge('borderDasharray')
color: styles.borderColor,
width: styles.borderWidth,
dasharray: styles.borderDasharray
})
this.addToEffectiveStyles(styles)
}
// 文字
text(node) {
const styles = {
color: this.merge('color'),
fontFamily: this.merge('fontFamily'),
fontSize: this.merge('fontSize'),
fontWeight: this.merge('fontWeight'),
fontStyle: this.merge('fontStyle'),
textDecoration: this.merge('textDecoration')
}
node
.fill({
color: this.merge('color')
color: styles.color
})
.css({
'font-family': this.merge('fontFamily'),
'font-size': this.merge('fontSize'),
'font-weight': this.merge('fontWeight'),
'font-style': this.merge('fontStyle'),
'text-decoration': this.merge('textDecoration')
'font-family': styles.fontFamily,
'font-size': styles.fontSize,
'font-weight': styles.fontWeight,
'font-style': styles.fontStyle,
'text-decoration': styles.textDecoration
})
this.addToEffectiveStyles(styles)
}
// 生成内联样式
createStyleText() {
const styles = {
color: this.merge('color'),
fontFamily: this.merge('fontFamily'),
fontSize: this.merge('fontSize'),
fontWeight: this.merge('fontWeight'),
fontStyle: this.merge('fontStyle'),
textDecoration: this.merge('textDecoration')
}
this.addToEffectiveStyles(styles)
return `
color: ${this.merge('color')};
font-family: ${this.merge('fontFamily')};
font-size: ${this.merge('fontSize') + 'px'};
font-weight: ${this.merge('fontWeight')};
font-style: ${this.merge('fontStyle')};
text-decoration: ${this.merge('textDecoration')}
color: ${styles.color};
font-family: ${styles.fontFamily};
font-size: ${styles.fontSize + 'px'};
font-weight: ${styles.fontWeight};
font-style: ${styles.fontStyle};
text-decoration: ${styles.textDecoration}
`
}
// 获取文本样式
getTextFontStyle() {
return {
italic: this.merge('fontStyle') === 'italic',
bold: this.merge('fontWeight'),
const styles = {
color: this.merge('color'),
fontFamily: this.merge('fontFamily'),
fontSize: this.merge('fontSize'),
fontFamily: this.merge('fontFamily')
fontWeight: this.merge('fontWeight'),
fontStyle: this.merge('fontStyle'),
textDecoration: this.merge('textDecoration')
}
this.addToEffectiveStyles(styles)
return {
italic: styles.fontStyle === 'italic',
bold: styles.fontWeight,
fontSize: styles.fontSize,
fontFamily: styles.fontFamily
}
}
// html文字节点
domText(node, fontSizeScale = 1, isMultiLine) {
node.style.fontFamily = this.merge('fontFamily')
node.style.fontSize = this.merge('fontSize') * fontSizeScale + 'px'
node.style.fontWeight = this.merge('fontWeight') || 'normal'
node.style.lineHeight = !isMultiLine ? 'normal' : this.merge('lineHeight')
node.style.fontStyle = this.merge('fontStyle')
const styles = {
color: this.merge('color'),
fontFamily: this.merge('fontFamily'),
fontSize: this.merge('fontSize'),
fontWeight: this.merge('fontWeight'),
fontStyle: this.merge('fontStyle'),
textDecoration: this.merge('textDecoration'),
lineHeight: this.merge('lineHeight')
}
this.addToEffectiveStyles(styles)
node.style.fontFamily = styles.fontFamily
node.style.fontSize = styles.fontSize * fontSizeScale + 'px'
node.style.fontWeight = styles.fontWeight || 'normal'
node.style.lineHeight = !isMultiLine ? 'normal' : styles.lineHeight
node.style.fontStyle = styles.fontStyle
}
// 标签文字
@@ -200,8 +266,12 @@ class Style {
// 内置图标
iconNode(node) {
const styles = {
color: this.merge('color')
}
this.addToEffectiveStyles(styles)
node.attr({
fill: this.merge('color')
fill: styles.color
})
}

View File

@@ -53,17 +53,22 @@ class Painter {
node.uid === this.painterNode.uid
)
return
const style = {}
let style = {}
// 格式刷节点所有生效的样式
if (!this.mindMap.opt.onlyPainterNodeCustomStyles) {
style = {
...this.painterNode.effectiveStyles
}
}
const painterNodeData = this.painterNode.getData()
Object.keys(painterNodeData).forEach(key => {
if (checkIsNodeStyleDataKey(key)) {
style[key] = painterNodeData[key]
}
})
// 先去除目标节点的样式
this.mindMap.renderer._handleRemoveCustomStyles(node.getData())
node.setStyles(style)
if (painterNodeData.activeStyle) {
node.setStyles(painterNodeData.activeStyle, true)
}
}
// 插件被移除前做的事情