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】插件 // 【OuterFrame】插件
outerFramePaddingX: 10, outerFramePaddingX: 10,
outerFramePaddingY: 10 outerFramePaddingY: 10,
// 【Painter】插件
// 是否只格式刷节点手动设置的样式,不考虑节点通过主题的应用的样式
onlyPainterNodeCustomStyles: false
} }

View File

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

View File

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

View File

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