mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-23 19:37:44 +08:00
Merge branch 'feature' into main
This commit is contained in:
commit
af9ee04aaf
File diff suppressed because one or more lines are too long
@ -10,7 +10,7 @@ import BatchExecution from './src/BatchExecution'
|
||||
import { layoutValueList, CONSTANTS } from './src/utils/constant'
|
||||
import { SVG } from '@svgdotjs/svg.js'
|
||||
import { simpleDeepClone } from './src/utils'
|
||||
import defaultTheme from './src/themes/default'
|
||||
import defaultTheme, { checkIsNodeSizeIndependenceConfig } from './src/themes/default'
|
||||
|
||||
// 默认选项配置
|
||||
const defaultOpt = {
|
||||
@ -120,7 +120,9 @@ const defaultOpt = {
|
||||
// }
|
||||
],
|
||||
// 节点最大缓存数量
|
||||
maxNodeCacheCount: 1000
|
||||
maxNodeCacheCount: 1000,
|
||||
// 关联线默认文字
|
||||
defaultAssociativeLineText: '关联'
|
||||
}
|
||||
|
||||
// 思维导图
|
||||
@ -265,7 +267,9 @@ class MindMap {
|
||||
// 设置主题配置
|
||||
setThemeConfig(config) {
|
||||
this.opt.themeConfig = config
|
||||
this.render(null, CONSTANTS.CHANGE_THEME)
|
||||
// 检查改变的是否是节点大小无关的主题属性
|
||||
let res = checkIsNodeSizeIndependenceConfig(config)
|
||||
this.render(null, res ? '' : CONSTANTS.CHANGE_THEME)
|
||||
}
|
||||
|
||||
// 获取自定义主题配置
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-mind-map",
|
||||
"version": "0.5.10-fix.2",
|
||||
"version": "0.5.11",
|
||||
"description": "一个简单的web在线思维导图",
|
||||
"authors": [
|
||||
{
|
||||
|
||||
@ -3,13 +3,13 @@ import { v4 as uuid } from 'uuid'
|
||||
import {
|
||||
getAssociativeLineTargetIndex,
|
||||
computeCubicBezierPathPoints,
|
||||
joinCubicBezierPath,
|
||||
cubicBezierPath,
|
||||
getNodePoint,
|
||||
computeNodePoints,
|
||||
getNodeLinePath,
|
||||
getDefaultControlPointOffsets
|
||||
getNodeLinePath
|
||||
} from './utils/associativeLineUtils'
|
||||
import associativeLineControlsMethods from './utils/associativeLineControls'
|
||||
import associativeLineTextMethods from './utils/associativeLineText'
|
||||
|
||||
// 关联线类
|
||||
class AssociativeLine {
|
||||
@ -46,6 +46,14 @@ class AssociativeLine {
|
||||
}
|
||||
// 节流一下,不然很卡
|
||||
this.checkOverlapNode = throttle(this.checkOverlapNode, 100, this)
|
||||
// 控制点相关方法
|
||||
Object.keys(associativeLineControlsMethods).forEach(item => {
|
||||
this[item] = associativeLineControlsMethods[item].bind(this)
|
||||
})
|
||||
// 关联线文字相关方法
|
||||
Object.keys(associativeLineTextMethods).forEach(item => {
|
||||
this[item] = associativeLineTextMethods[item].bind(this)
|
||||
})
|
||||
this.bindEvent()
|
||||
}
|
||||
|
||||
@ -89,6 +97,8 @@ class AssociativeLine {
|
||||
window.addEventListener('mouseup', e => {
|
||||
this.onControlPointMouseup(e)
|
||||
})
|
||||
// 缩放事件
|
||||
this.mindMap.on('scale', this.onScale)
|
||||
}
|
||||
|
||||
// 创建箭头
|
||||
@ -177,36 +187,46 @@ class AssociativeLine {
|
||||
.stroke({ width: associativeLineActiveWidth, color: 'transparent' })
|
||||
.fill({ color: 'none' })
|
||||
clickPath.plot(pathStr)
|
||||
// 文字
|
||||
let text = this.createText({ path, clickPath, node, toNode, startPoint, endPoint, controlPoints })
|
||||
// 点击事件
|
||||
clickPath.click(e => {
|
||||
e.stopPropagation()
|
||||
// 如果当前存在激活节点,那么取消激活节点
|
||||
if (this.mindMap.renderer.activeNodeList.length > 0) {
|
||||
this.clearActiveNodes()
|
||||
} else {
|
||||
// 否则清除当前的关联线的激活状态,如果有的话
|
||||
this.clearActiveLine()
|
||||
// 保存当前激活的关联线信息
|
||||
this.activeLine = [path, clickPath, node, toNode]
|
||||
// 让不可见的点击线显示
|
||||
clickPath.stroke({ color: associativeLineActiveColor })
|
||||
// 渲染控制点和连线
|
||||
this.renderControls(
|
||||
startPoint,
|
||||
endPoint,
|
||||
controlPoints[0],
|
||||
controlPoints[1]
|
||||
)
|
||||
this.mindMap.emit(
|
||||
'associative_line_click',
|
||||
path,
|
||||
clickPath,
|
||||
node,
|
||||
toNode
|
||||
)
|
||||
}
|
||||
this.setActiveLine({ path, clickPath, text, node, toNode, startPoint, endPoint, controlPoints })
|
||||
})
|
||||
this.lineList.push([path, clickPath, node, toNode])
|
||||
// 渲染关联线文字
|
||||
this.renderText(this.getText(node, toNode), path, text)
|
||||
this.lineList.push([path, clickPath, text, node, toNode])
|
||||
}
|
||||
|
||||
// 激活某根关联线
|
||||
setActiveLine({ path, clickPath, text, node, toNode, startPoint, endPoint, controlPoints }) {
|
||||
let {
|
||||
associativeLineActiveColor
|
||||
} = this.mindMap.themeConfig
|
||||
// 如果当前存在激活节点,那么取消激活节点
|
||||
if (this.mindMap.renderer.activeNodeList.length > 0) {
|
||||
this.clearActiveNodes()
|
||||
} else {
|
||||
// 否则清除当前的关联线的激活状态,如果有的话
|
||||
this.clearActiveLine()
|
||||
// 保存当前激活的关联线信息
|
||||
this.activeLine = [path, clickPath, text, node, toNode]
|
||||
// 让不可见的点击线显示
|
||||
clickPath.stroke({ color: associativeLineActiveColor })
|
||||
// 如果没有输入过关联线文字,那么显示默认文字
|
||||
if (!this.getText(node, toNode)) {
|
||||
this.renderText(this.mindMap.opt.defaultAssociativeLineText, path, text)
|
||||
}
|
||||
// 渲染控制点和连线
|
||||
this.renderControls(
|
||||
startPoint,
|
||||
endPoint,
|
||||
controlPoints[0],
|
||||
controlPoints[1]
|
||||
)
|
||||
this.mindMap.emit('associative_line_click', path, clickPath, node, toNode)
|
||||
}
|
||||
}
|
||||
|
||||
// 移除所有连接线
|
||||
@ -214,6 +234,7 @@ class AssociativeLine {
|
||||
this.lineList.forEach(line => {
|
||||
line[0].remove()
|
||||
line[1].remove()
|
||||
line[2].remove()
|
||||
})
|
||||
this.lineList = []
|
||||
}
|
||||
@ -253,7 +274,8 @@ class AssociativeLine {
|
||||
updateCreatingLine(e) {
|
||||
let { x, y } = this.getTransformedEventPos(e)
|
||||
let startPoint = getNodePoint(this.creatingStartNode)
|
||||
let pathStr = cubicBezierPath(startPoint.x, startPoint.y, x, y)
|
||||
let offsetX = x > startPoint.x ? -10 : 10
|
||||
let pathStr = cubicBezierPath(startPoint.x, startPoint.y, x + offsetX, y)
|
||||
this.creatingLine.plot(pathStr)
|
||||
this.checkOverlapNode(x, y)
|
||||
}
|
||||
@ -349,20 +371,33 @@ class AssociativeLine {
|
||||
// 删除连接线
|
||||
removeLine() {
|
||||
if (!this.activeLine) return
|
||||
let [, , node, toNode] = this.activeLine
|
||||
let [, , , node, toNode] = this.activeLine
|
||||
this.removeControls()
|
||||
let { associativeLineTargets, associativeLineTargetControlOffsets } =
|
||||
let { associativeLineTargets, associativeLineTargetControlOffsets, associativeLineText } =
|
||||
node.nodeData.data
|
||||
let targetIndex = getAssociativeLineTargetIndex(node, toNode)
|
||||
// 更新关联线文本数据
|
||||
let newAssociativeLineText = {}
|
||||
if (associativeLineText) {
|
||||
Object.keys(associativeLineText).forEach((item) => {
|
||||
if (item !== toNode.nodeData.data.id) {
|
||||
newAssociativeLineText[item] = associativeLineText[item]
|
||||
}
|
||||
})
|
||||
}
|
||||
this.mindMap.execCommand('SET_NODE_DATA', node, {
|
||||
// 目标
|
||||
associativeLineTargets: associativeLineTargets.filter((_, index) => {
|
||||
return index !== targetIndex
|
||||
}),
|
||||
// 偏移量
|
||||
associativeLineTargetControlOffsets: associativeLineTargetControlOffsets
|
||||
? associativeLineTargetControlOffsets.filter((_, index) => {
|
||||
return index !== targetIndex
|
||||
})
|
||||
: []
|
||||
: [],
|
||||
// 文本
|
||||
associativeLineText: newAssociativeLineText
|
||||
})
|
||||
}
|
||||
|
||||
@ -376,9 +411,16 @@ class AssociativeLine {
|
||||
// 清除激活的线
|
||||
clearActiveLine() {
|
||||
if (this.activeLine) {
|
||||
this.activeLine[1].stroke({
|
||||
let [, clickPath, text, node, toNode] = this.activeLine
|
||||
clickPath.stroke({
|
||||
color: 'transparent'
|
||||
})
|
||||
// 隐藏关联线文本编辑框
|
||||
this.hideEditTextBox()
|
||||
// 如果当前关联线没有文字,则清空文字节点
|
||||
if (!this.getText(node, toNode)) {
|
||||
text.clear()
|
||||
}
|
||||
this.activeLine = null
|
||||
this.removeControls()
|
||||
}
|
||||
@ -391,6 +433,7 @@ class AssociativeLine {
|
||||
this.lineList.forEach(line => {
|
||||
line[0].hide()
|
||||
line[1].hide()
|
||||
line[2].hide()
|
||||
})
|
||||
this.hideControls()
|
||||
}
|
||||
@ -401,225 +444,11 @@ class AssociativeLine {
|
||||
this.lineList.forEach(line => {
|
||||
line[0].show()
|
||||
line[1].show()
|
||||
line[2].show()
|
||||
})
|
||||
this.showControls()
|
||||
this.isNodeDragging = false
|
||||
}
|
||||
|
||||
// 创建控制点、连线节点
|
||||
createControlNodes() {
|
||||
let { associativeLineActiveColor } = this.mindMap.themeConfig
|
||||
// 连线
|
||||
this.controlLine1 = this.draw
|
||||
.line()
|
||||
.stroke({ color: associativeLineActiveColor, width: 2 })
|
||||
this.controlLine2 = this.draw
|
||||
.line()
|
||||
.stroke({ color: associativeLineActiveColor, width: 2 })
|
||||
// 控制点
|
||||
this.controlPoint1 = this.createOneControlNode('controlPoint1')
|
||||
this.controlPoint2 = this.createOneControlNode('controlPoint2')
|
||||
}
|
||||
|
||||
// 创建控制点
|
||||
createOneControlNode(pointKey) {
|
||||
let { associativeLineActiveColor } = this.mindMap.themeConfig
|
||||
return this.draw
|
||||
.circle(this.controlPointDiameter)
|
||||
.stroke({ color: associativeLineActiveColor })
|
||||
.fill({ color: '#fff' })
|
||||
.click(e => {
|
||||
e.stopPropagation()
|
||||
})
|
||||
.mousedown(e => {
|
||||
this.onControlPointMousedown(e, pointKey)
|
||||
})
|
||||
}
|
||||
|
||||
// 控制点的鼠标按下事件
|
||||
onControlPointMousedown(e, pointKey) {
|
||||
e.stopPropagation()
|
||||
this.isControlPointMousedown = true
|
||||
this.mousedownControlPointKey = pointKey
|
||||
}
|
||||
|
||||
// 控制点的鼠标移动事件
|
||||
onControlPointMousemove(e) {
|
||||
if (
|
||||
!this.isControlPointMousedown ||
|
||||
!this.mousedownControlPointKey ||
|
||||
!this[this.mousedownControlPointKey]
|
||||
)
|
||||
return
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
let radius = this.controlPointDiameter / 2
|
||||
// 转换鼠标当前的位置
|
||||
let { x, y } = this.getTransformedEventPos(e)
|
||||
this.controlPointMousemoveState.pos = {
|
||||
x,
|
||||
y
|
||||
}
|
||||
// 更新当前拖拽的控制点的位置
|
||||
this[this.mousedownControlPointKey].x(x - radius).y(y - radius)
|
||||
let [path, clickPath, node, toNode] = this.activeLine
|
||||
let [startPoint, endPoint] = computeNodePoints(node, toNode)
|
||||
this.controlPointMousemoveState.startPoint = startPoint
|
||||
this.controlPointMousemoveState.endPoint = endPoint
|
||||
let targetIndex = getAssociativeLineTargetIndex(node, toNode)
|
||||
this.controlPointMousemoveState.targetIndex = targetIndex
|
||||
let offsets = []
|
||||
let associativeLineTargetControlOffsets = node.nodeData.data.associativeLineTargetControlOffsets
|
||||
if (!associativeLineTargetControlOffsets) {
|
||||
// 兼容0.4.5版本,没有associativeLineTargetControlOffsets的情况
|
||||
offsets = getDefaultControlPointOffsets(startPoint, endPoint)
|
||||
} else {
|
||||
offsets = associativeLineTargetControlOffsets[targetIndex]
|
||||
}
|
||||
let point1 = null
|
||||
let point2 = null
|
||||
// 拖拽的是控制点1
|
||||
if (this.mousedownControlPointKey === 'controlPoint1') {
|
||||
point1 = {
|
||||
x,
|
||||
y
|
||||
}
|
||||
point2 = {
|
||||
x: endPoint.x + offsets[1].x,
|
||||
y: endPoint.y + offsets[1].y
|
||||
}
|
||||
// 更新控制点1的连线
|
||||
this.controlLine1.plot(startPoint.x, startPoint.y, point1.x, point1.y)
|
||||
} else {
|
||||
// 拖拽的是控制点2
|
||||
point1 = {
|
||||
x: startPoint.x + offsets[0].x,
|
||||
y: startPoint.y + offsets[0].y
|
||||
}
|
||||
point2 = {
|
||||
x,
|
||||
y
|
||||
}
|
||||
// 更新控制点2的连线
|
||||
this.controlLine2.plot(endPoint.x, endPoint.y, point2.x, point2.y)
|
||||
}
|
||||
// 更新关联线
|
||||
let pathStr = joinCubicBezierPath(startPoint, endPoint, point1, point2)
|
||||
path.plot(pathStr)
|
||||
clickPath.plot(pathStr)
|
||||
}
|
||||
|
||||
// 控制点的鼠标移动事件
|
||||
onControlPointMouseup(e) {
|
||||
if (!this.isControlPointMousedown) return
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
let { pos, startPoint, endPoint, targetIndex } =
|
||||
this.controlPointMousemoveState
|
||||
let [, , node] = this.activeLine
|
||||
let offsetList = []
|
||||
let associativeLineTargetControlOffsets = node.nodeData.data.associativeLineTargetControlOffsets
|
||||
if (!associativeLineTargetControlOffsets) {
|
||||
// 兼容0.4.5版本,没有associativeLineTargetControlOffsets的情况
|
||||
offsetList[targetIndex] = getDefaultControlPointOffsets(startPoint, endPoint)
|
||||
} else {
|
||||
offsetList = associativeLineTargetControlOffsets
|
||||
}
|
||||
let offset1 = null
|
||||
let offset2 = null
|
||||
if (this.mousedownControlPointKey === 'controlPoint1') {
|
||||
// 更新控制点1数据
|
||||
offset1 = {
|
||||
x: pos.x - startPoint.x,
|
||||
y: pos.y - startPoint.y
|
||||
}
|
||||
offset2 = offsetList[targetIndex][1]
|
||||
} else {
|
||||
// 更新控制点2数据
|
||||
offset1 = offsetList[targetIndex][0]
|
||||
offset2 = {
|
||||
x: pos.x - endPoint.x,
|
||||
y: pos.y - endPoint.y
|
||||
}
|
||||
}
|
||||
offsetList[targetIndex] = [offset1, offset2]
|
||||
this.mindMap.execCommand('SET_NODE_DATA', node, {
|
||||
associativeLineTargetControlOffsets: offsetList
|
||||
})
|
||||
// 这里要加个setTimeout0是因为draw_click事件比mouseup事件触发的晚,所以重置isControlPointMousedown需要等draw_click事件触发完以后
|
||||
setTimeout(() => {
|
||||
this.resetControlPoint()
|
||||
}, 0)
|
||||
}
|
||||
|
||||
// 复位控制点移动
|
||||
resetControlPoint() {
|
||||
this.isControlPointMousedown = false
|
||||
this.mousedownControlPointKey = ''
|
||||
this.controlPointMousemoveState = {
|
||||
pos: null,
|
||||
startPoint: null,
|
||||
endPoint: null,
|
||||
targetIndex: ''
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染控制点
|
||||
renderControls(startPoint, endPoint, point1, point2) {
|
||||
if (!this.controlLine1) {
|
||||
this.createControlNodes()
|
||||
}
|
||||
let radius = this.controlPointDiameter / 2
|
||||
// 控制点和起终点的连线
|
||||
this.controlLine1.plot(startPoint.x, startPoint.y, point1.x, point1.y)
|
||||
this.controlLine2.plot(endPoint.x, endPoint.y, point2.x, point2.y)
|
||||
// 控制点
|
||||
this.controlPoint1.x(point1.x - radius).y(point1.y - radius)
|
||||
this.controlPoint2.x(point2.x - radius).y(point2.y - radius)
|
||||
}
|
||||
|
||||
// 删除控制点
|
||||
removeControls() {
|
||||
if (!this.controlLine1) return
|
||||
;[
|
||||
this.controlLine1,
|
||||
this.controlLine2,
|
||||
this.controlPoint1,
|
||||
this.controlPoint2
|
||||
].forEach(item => {
|
||||
item.remove()
|
||||
})
|
||||
this.controlLine1 = null
|
||||
this.controlLine2 = null
|
||||
this.controlPoint1 = null
|
||||
this.controlPoint2 = null
|
||||
}
|
||||
|
||||
// 隐藏控制点
|
||||
hideControls() {
|
||||
if (!this.controlLine1) return
|
||||
;[
|
||||
this.controlLine1,
|
||||
this.controlLine2,
|
||||
this.controlPoint1,
|
||||
this.controlPoint2
|
||||
].forEach(item => {
|
||||
item.hide()
|
||||
})
|
||||
}
|
||||
|
||||
// 显示控制点
|
||||
showControls() {
|
||||
if (!this.controlLine1) return
|
||||
;[
|
||||
this.controlLine1,
|
||||
this.controlLine2,
|
||||
this.controlPoint1,
|
||||
this.controlPoint2
|
||||
].forEach(item => {
|
||||
item.show()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
AssociativeLine.instanceName = 'associativeLine'
|
||||
|
||||
@ -46,7 +46,7 @@ export default class KeyCommand {
|
||||
if (this.mindMap.richText && this.mindMap.richText.showTextEdit) {
|
||||
return
|
||||
}
|
||||
if (this.mindMap.renderer.textEdit.showTextEdit) {
|
||||
if (this.mindMap.renderer.textEdit.showTextEdit || (this.mindMap.associativeLine && this.mindMap.associativeLine.showTextEdit)) {
|
||||
return
|
||||
}
|
||||
this.isInSvg = false
|
||||
|
||||
@ -34,6 +34,14 @@ export default {
|
||||
associativeLineActiveWidth: 8,
|
||||
// 关联线激活状态的颜色
|
||||
associativeLineActiveColor: 'rgba(2, 167, 240, 1)',
|
||||
// 关联线文字颜色
|
||||
associativeLineTextColor: 'rgb(51, 51, 51)',
|
||||
// 关联线文字大小
|
||||
associativeLineTextFontSize: 14,
|
||||
// 关联线文字行高
|
||||
associativeLineTextLineHeight: 1.2,
|
||||
// 关联线文字字体
|
||||
associativeLineTextFontFamily: '微软雅黑, Microsoft YaHei',
|
||||
// 背景颜色
|
||||
backgroundColor: '#fafafa',
|
||||
// 背景图片
|
||||
@ -148,4 +156,38 @@ export const supportActiveStyle = [
|
||||
'borderRadius'
|
||||
]
|
||||
|
||||
// 检测主题配置是否是节点大小无关的
|
||||
const nodeSizeIndependenceList = [
|
||||
'lineWidth',
|
||||
'lineColor',
|
||||
'lineDasharray',
|
||||
'lineStyle',
|
||||
'generalizationLineWidth',
|
||||
'generalizationLineColor',
|
||||
'associativeLineWidth',
|
||||
'associativeLineColor',
|
||||
'associativeLineActiveWidth',
|
||||
'associativeLineActiveColor',
|
||||
'associativeLineTextColor',
|
||||
'associativeLineTextFontSize',
|
||||
'associativeLineTextLineHeight',
|
||||
'associativeLineTextFontFamily',
|
||||
'backgroundColor',
|
||||
'backgroundImage',
|
||||
'backgroundRepeat',
|
||||
'backgroundPosition',
|
||||
'backgroundSize'
|
||||
]
|
||||
export const checkIsNodeSizeIndependenceConfig = (config) => {
|
||||
let keys = Object.keys(config)
|
||||
for(let i = 0; i < keys.length; i++) {
|
||||
if (!nodeSizeIndependenceList.find((item) => {
|
||||
return item === keys[i]
|
||||
})) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export const lineStyleProps = ['lineColor', 'lineDasharray', 'lineWidth']
|
||||
|
||||
241
simple-mind-map/src/utils/associativeLineControls.js
Normal file
241
simple-mind-map/src/utils/associativeLineControls.js
Normal file
@ -0,0 +1,241 @@
|
||||
import {
|
||||
getAssociativeLineTargetIndex,
|
||||
joinCubicBezierPath,
|
||||
computeNodePoints,
|
||||
getDefaultControlPointOffsets
|
||||
} from './associativeLineUtils'
|
||||
|
||||
// 创建控制点、连线节点
|
||||
function createControlNodes() {
|
||||
let { associativeLineActiveColor } = this.mindMap.themeConfig
|
||||
// 连线
|
||||
this.controlLine1 = this.draw
|
||||
.line()
|
||||
.stroke({ color: associativeLineActiveColor, width: 2 })
|
||||
this.controlLine2 = this.draw
|
||||
.line()
|
||||
.stroke({ color: associativeLineActiveColor, width: 2 })
|
||||
// 控制点
|
||||
this.controlPoint1 = this.createOneControlNode('controlPoint1')
|
||||
this.controlPoint2 = this.createOneControlNode('controlPoint2')
|
||||
}
|
||||
|
||||
// 创建控制点
|
||||
function createOneControlNode(pointKey) {
|
||||
let { associativeLineActiveColor } = this.mindMap.themeConfig
|
||||
return this.draw
|
||||
.circle(this.controlPointDiameter)
|
||||
.stroke({ color: associativeLineActiveColor })
|
||||
.fill({ color: '#fff' })
|
||||
.click(e => {
|
||||
e.stopPropagation()
|
||||
})
|
||||
.mousedown(e => {
|
||||
this.onControlPointMousedown(e, pointKey)
|
||||
})
|
||||
}
|
||||
|
||||
// 控制点的鼠标按下事件
|
||||
function onControlPointMousedown(e, pointKey) {
|
||||
e.stopPropagation()
|
||||
this.isControlPointMousedown = true
|
||||
this.mousedownControlPointKey = pointKey
|
||||
}
|
||||
|
||||
// 控制点的鼠标移动事件
|
||||
function onControlPointMousemove(e) {
|
||||
if (
|
||||
!this.isControlPointMousedown ||
|
||||
!this.mousedownControlPointKey ||
|
||||
!this[this.mousedownControlPointKey]
|
||||
)
|
||||
return
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
let radius = this.controlPointDiameter / 2
|
||||
// 转换鼠标当前的位置
|
||||
let { x, y } = this.getTransformedEventPos(e)
|
||||
this.controlPointMousemoveState.pos = {
|
||||
x,
|
||||
y
|
||||
}
|
||||
// 更新当前拖拽的控制点的位置
|
||||
this[this.mousedownControlPointKey].x(x - radius).y(y - radius)
|
||||
let [path, clickPath, text, node, toNode] = this.activeLine
|
||||
let [startPoint, endPoint] = computeNodePoints(node, toNode)
|
||||
this.controlPointMousemoveState.startPoint = startPoint
|
||||
this.controlPointMousemoveState.endPoint = endPoint
|
||||
let targetIndex = getAssociativeLineTargetIndex(node, toNode)
|
||||
this.controlPointMousemoveState.targetIndex = targetIndex
|
||||
let offsets = []
|
||||
let associativeLineTargetControlOffsets =
|
||||
node.nodeData.data.associativeLineTargetControlOffsets
|
||||
if (!associativeLineTargetControlOffsets) {
|
||||
// 兼容0.4.5版本,没有associativeLineTargetControlOffsets的情况
|
||||
offsets = getDefaultControlPointOffsets(startPoint, endPoint)
|
||||
} else {
|
||||
offsets = associativeLineTargetControlOffsets[targetIndex]
|
||||
}
|
||||
let point1 = null
|
||||
let point2 = null
|
||||
// 拖拽的是控制点1
|
||||
if (this.mousedownControlPointKey === 'controlPoint1') {
|
||||
point1 = {
|
||||
x,
|
||||
y
|
||||
}
|
||||
point2 = {
|
||||
x: endPoint.x + offsets[1].x,
|
||||
y: endPoint.y + offsets[1].y
|
||||
}
|
||||
// 更新控制点1的连线
|
||||
this.controlLine1.plot(startPoint.x, startPoint.y, point1.x, point1.y)
|
||||
} else {
|
||||
// 拖拽的是控制点2
|
||||
point1 = {
|
||||
x: startPoint.x + offsets[0].x,
|
||||
y: startPoint.y + offsets[0].y
|
||||
}
|
||||
point2 = {
|
||||
x,
|
||||
y
|
||||
}
|
||||
// 更新控制点2的连线
|
||||
this.controlLine2.plot(endPoint.x, endPoint.y, point2.x, point2.y)
|
||||
}
|
||||
// 更新关联线
|
||||
let pathStr = joinCubicBezierPath(startPoint, endPoint, point1, point2)
|
||||
path.plot(pathStr)
|
||||
clickPath.plot(pathStr)
|
||||
this.updateTextPos(path, text)
|
||||
this.updateTextEditBoxPos(text)
|
||||
}
|
||||
|
||||
// 控制点的鼠标移动事件
|
||||
function onControlPointMouseup(e) {
|
||||
if (!this.isControlPointMousedown) return
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
let { pos, startPoint, endPoint, targetIndex } =
|
||||
this.controlPointMousemoveState
|
||||
let [, , , node] = this.activeLine
|
||||
let offsetList = []
|
||||
let associativeLineTargetControlOffsets =
|
||||
node.nodeData.data.associativeLineTargetControlOffsets
|
||||
if (!associativeLineTargetControlOffsets) {
|
||||
// 兼容0.4.5版本,没有associativeLineTargetControlOffsets的情况
|
||||
offsetList[targetIndex] = getDefaultControlPointOffsets(
|
||||
startPoint,
|
||||
endPoint
|
||||
)
|
||||
} else {
|
||||
offsetList = associativeLineTargetControlOffsets
|
||||
}
|
||||
let offset1 = null
|
||||
let offset2 = null
|
||||
if (this.mousedownControlPointKey === 'controlPoint1') {
|
||||
// 更新控制点1数据
|
||||
offset1 = {
|
||||
x: pos.x - startPoint.x,
|
||||
y: pos.y - startPoint.y
|
||||
}
|
||||
offset2 = offsetList[targetIndex][1]
|
||||
} else {
|
||||
// 更新控制点2数据
|
||||
offset1 = offsetList[targetIndex][0]
|
||||
offset2 = {
|
||||
x: pos.x - endPoint.x,
|
||||
y: pos.y - endPoint.y
|
||||
}
|
||||
}
|
||||
offsetList[targetIndex] = [offset1, offset2]
|
||||
this.mindMap.execCommand('SET_NODE_DATA', node, {
|
||||
associativeLineTargetControlOffsets: offsetList
|
||||
})
|
||||
// 这里要加个setTimeout0是因为draw_click事件比mouseup事件触发的晚,所以重置isControlPointMousedown需要等draw_click事件触发完以后
|
||||
setTimeout(() => {
|
||||
this.resetControlPoint()
|
||||
}, 0)
|
||||
}
|
||||
|
||||
// 复位控制点移动
|
||||
function resetControlPoint() {
|
||||
this.isControlPointMousedown = false
|
||||
this.mousedownControlPointKey = ''
|
||||
this.controlPointMousemoveState = {
|
||||
pos: null,
|
||||
startPoint: null,
|
||||
endPoint: null,
|
||||
targetIndex: ''
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染控制点
|
||||
function renderControls(startPoint, endPoint, point1, point2) {
|
||||
if (!this.controlLine1) {
|
||||
this.createControlNodes()
|
||||
}
|
||||
let radius = this.controlPointDiameter / 2
|
||||
// 控制点和起终点的连线
|
||||
this.controlLine1.plot(startPoint.x, startPoint.y, point1.x, point1.y)
|
||||
this.controlLine2.plot(endPoint.x, endPoint.y, point2.x, point2.y)
|
||||
// 控制点
|
||||
this.controlPoint1.x(point1.x - radius).y(point1.y - radius)
|
||||
this.controlPoint2.x(point2.x - radius).y(point2.y - radius)
|
||||
}
|
||||
|
||||
// 删除控制点
|
||||
function removeControls() {
|
||||
if (!this.controlLine1) return
|
||||
;[
|
||||
this.controlLine1,
|
||||
this.controlLine2,
|
||||
this.controlPoint1,
|
||||
this.controlPoint2
|
||||
].forEach(item => {
|
||||
item.remove()
|
||||
})
|
||||
this.controlLine1 = null
|
||||
this.controlLine2 = null
|
||||
this.controlPoint1 = null
|
||||
this.controlPoint2 = null
|
||||
}
|
||||
|
||||
// 隐藏控制点
|
||||
function hideControls() {
|
||||
if (!this.controlLine1) return
|
||||
;[
|
||||
this.controlLine1,
|
||||
this.controlLine2,
|
||||
this.controlPoint1,
|
||||
this.controlPoint2
|
||||
].forEach(item => {
|
||||
item.hide()
|
||||
})
|
||||
}
|
||||
|
||||
// 显示控制点
|
||||
function showControls() {
|
||||
if (!this.controlLine1) return
|
||||
;[
|
||||
this.controlLine1,
|
||||
this.controlLine2,
|
||||
this.controlPoint1,
|
||||
this.controlPoint2
|
||||
].forEach(item => {
|
||||
item.show()
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
createControlNodes,
|
||||
createOneControlNode,
|
||||
onControlPointMousedown,
|
||||
onControlPointMousemove,
|
||||
onControlPointMouseup,
|
||||
resetControlPoint,
|
||||
renderControls,
|
||||
removeControls,
|
||||
hideControls,
|
||||
showControls
|
||||
}
|
||||
167
simple-mind-map/src/utils/associativeLineText.js
Normal file
167
simple-mind-map/src/utils/associativeLineText.js
Normal file
@ -0,0 +1,167 @@
|
||||
import { Text } from '@svgdotjs/svg.js'
|
||||
import { getStrWithBrFromHtml } from './index'
|
||||
|
||||
// 创建文字节点
|
||||
function createText(data) {
|
||||
let g = this.draw.group()
|
||||
const setActive = () => {
|
||||
if (
|
||||
!this.activeLine ||
|
||||
this.activeLine[3] !== data.node ||
|
||||
this.activeLine[4] !== data.toNode
|
||||
) {
|
||||
this.setActiveLine({
|
||||
...data,
|
||||
text: g
|
||||
})
|
||||
}
|
||||
}
|
||||
g.click(e => {
|
||||
e.stopPropagation()
|
||||
setActive()
|
||||
})
|
||||
g.on('dblclick', e => {
|
||||
e.stopPropagation()
|
||||
setActive()
|
||||
if (!this.activeLine) return
|
||||
this.showEditTextBox(g)
|
||||
})
|
||||
return g
|
||||
}
|
||||
|
||||
// 显示文本编辑框
|
||||
function showEditTextBox(g) {
|
||||
this.mindMap.emit('before_show_text_edit')
|
||||
// 注册回车快捷键
|
||||
this.mindMap.keyCommand.addShortcut('Enter', () => {
|
||||
this.hideEditTextBox()
|
||||
})
|
||||
|
||||
if (!this.textEditNode) {
|
||||
this.textEditNode = document.createElement('div')
|
||||
this.textEditNode.style.cssText = `position:fixed;box-sizing: border-box;background-color:#fff;box-shadow: 0 0 20px rgba(0,0,0,.5);padding: 3px 5px;margin-left: -5px;margin-top: -3px;outline: none; word-break: break-all;`
|
||||
this.textEditNode.setAttribute('contenteditable', true)
|
||||
this.textEditNode.addEventListener('keyup', e => {
|
||||
e.stopPropagation()
|
||||
})
|
||||
this.textEditNode.addEventListener('click', e => {
|
||||
e.stopPropagation()
|
||||
})
|
||||
document.body.appendChild(this.textEditNode)
|
||||
}
|
||||
let {
|
||||
associativeLineTextFontSize,
|
||||
associativeLineTextFontFamily,
|
||||
associativeLineTextLineHeight
|
||||
} = this.mindMap.themeConfig
|
||||
let scale = this.mindMap.view.scale
|
||||
let [, , , node, toNode] = this.activeLine
|
||||
let textLines = (
|
||||
this.getText(node, toNode) || this.mindMap.opt.defaultAssociativeLineText
|
||||
).split(/\n/gim)
|
||||
this.textEditNode.style.fontFamily = associativeLineTextFontFamily
|
||||
this.textEditNode.style.fontSize = associativeLineTextFontSize * scale + 'px'
|
||||
this.textEditNode.style.lineHeight = textLines.length > 1 ? associativeLineTextLineHeight : 'normal'
|
||||
this.textEditNode.style.zIndex = this.mindMap.opt.nodeTextEditZIndex
|
||||
this.textEditNode.innerHTML = textLines.join('<br>')
|
||||
this.textEditNode.style.display = 'block'
|
||||
this.updateTextEditBoxPos(g)
|
||||
this.showTextEdit = true
|
||||
}
|
||||
|
||||
// 处理画布缩放
|
||||
function onScale() {
|
||||
this.hideEditTextBox()
|
||||
}
|
||||
|
||||
// 更新文本编辑框位置
|
||||
function updateTextEditBoxPos(g) {
|
||||
let rect = g.node.getBoundingClientRect()
|
||||
this.textEditNode.style.minWidth = rect.width + 10 + 'px'
|
||||
this.textEditNode.style.minHeight = rect.height + 6 + 'px'
|
||||
this.textEditNode.style.left = rect.left + 'px'
|
||||
this.textEditNode.style.top = rect.top + 'px'
|
||||
}
|
||||
|
||||
// 隐藏文本编辑框
|
||||
function hideEditTextBox() {
|
||||
if (!this.showTextEdit) {
|
||||
return
|
||||
}
|
||||
let [path, , text, node, toNode] = this.activeLine
|
||||
let str = getStrWithBrFromHtml(this.textEditNode.innerHTML)
|
||||
this.mindMap.execCommand('SET_NODE_DATA', node, {
|
||||
associativeLineText: {
|
||||
...(node.nodeData.data.associativeLineText || {}),
|
||||
[toNode.nodeData.data.id]: str
|
||||
}
|
||||
})
|
||||
this.textEditNode.style.display = 'none'
|
||||
this.textEditNode.innerHTML = ''
|
||||
this.showTextEdit = false
|
||||
this.renderText(str, path, text)
|
||||
this.mindMap.emit('hide_text_edit')
|
||||
}
|
||||
|
||||
// 获取某根关联线的文字
|
||||
function getText(node, toNode) {
|
||||
let obj = node.nodeData.data.associativeLineText
|
||||
if (!obj) {
|
||||
return ''
|
||||
}
|
||||
return obj[toNode.nodeData.data.id] || ''
|
||||
}
|
||||
|
||||
// 渲染关联线文字
|
||||
function renderText(str, path, text) {
|
||||
if (!str) return
|
||||
let { associativeLineTextFontSize, associativeLineTextLineHeight } =
|
||||
this.mindMap.themeConfig
|
||||
text.clear()
|
||||
let textArr = str.split(/\n/gim)
|
||||
textArr.forEach((item, index) => {
|
||||
let node = new Text().text(item)
|
||||
node.y(associativeLineTextFontSize * associativeLineTextLineHeight * index)
|
||||
this.styleText(node)
|
||||
text.add(node)
|
||||
})
|
||||
updateTextPos(path, text)
|
||||
}
|
||||
|
||||
// 给文本设置样式
|
||||
function styleText(node) {
|
||||
let {
|
||||
associativeLineTextColor,
|
||||
associativeLineTextFontSize,
|
||||
associativeLineTextFontFamily
|
||||
} = this.mindMap.themeConfig
|
||||
node
|
||||
.fill({
|
||||
color: associativeLineTextColor
|
||||
})
|
||||
.css({
|
||||
'font-family': associativeLineTextFontFamily,
|
||||
'font-size': associativeLineTextFontSize
|
||||
})
|
||||
}
|
||||
|
||||
// 更新关联线文字位置
|
||||
function updateTextPos(path, text) {
|
||||
let pathLength = path.length()
|
||||
let centerPoint = path.pointAt(pathLength / 2)
|
||||
let { width: textWidth, height: textHeight } = text.bbox()
|
||||
text.x(centerPoint.x - textWidth / 2)
|
||||
text.y(centerPoint.y - textHeight / 2)
|
||||
}
|
||||
|
||||
export default {
|
||||
getText,
|
||||
createText,
|
||||
styleText,
|
||||
onScale,
|
||||
showEditTextBox,
|
||||
hideEditTextBox,
|
||||
updateTextEditBoxPos,
|
||||
renderText,
|
||||
updateTextPos
|
||||
}
|
||||
@ -4,9 +4,9 @@
|
||||
|
||||
> The function of adjusting associated line control points is supported from v0.4.6+
|
||||
|
||||
This plugin is used to support the addition of associative lines.
|
||||
> Relevance support for text editing starting from v0.5.11+
|
||||
|
||||
The plugin is currently not fully functional, and does not support adding text to association lines.
|
||||
This plugin is used to support the addition of associative lines.
|
||||
|
||||
## Register
|
||||
|
||||
|
||||
@ -7,8 +7,10 @@
|
||||
<blockquote>
|
||||
<p>The function of adjusting associated line control points is supported from v0.4.6+</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Relevance support for text editing starting from v0.5.11+</p>
|
||||
</blockquote>
|
||||
<p>This plugin is used to support the addition of associative lines.</p>
|
||||
<p>The plugin is currently not fully functional, and does not support adding text to association lines.</p>
|
||||
<h2>Register</h2>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map'</span>
|
||||
<span class="hljs-keyword">import</span> AssociativeLine <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/AssociativeLine.js'</span>
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
## 0.5.11
|
||||
|
||||
New: Supports associative text editing.
|
||||
|
||||
optimization: Optimizing theme configuration updates, changing configurations that do not involve node size does not trigger node recalculation.
|
||||
|
||||
## 0.5.10
|
||||
|
||||
New: Optimize node reuse logic using LRU caching algorithm.
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.5.11</h2>
|
||||
<p>New: Supports associative text editing.</p>
|
||||
<p>optimization: Optimizing theme configuration updates, changing configurations that do not involve node size does not trigger node recalculation.</p>
|
||||
<h2>0.5.10</h2>
|
||||
<p>New: Optimize node reuse logic using LRU caching algorithm.</p>
|
||||
<h2>0.5.10-fix.1</h2>
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
|
||||
> 调整关联线控制点的功能从v0.4.6+开始支持
|
||||
|
||||
该插件用于支持添加关联线。
|
||||
> 关联性支持文本编辑从v0.5.11+开始支持
|
||||
|
||||
该插件目前功能还不完善,不支持在关联线上添加文字。
|
||||
该插件用于支持添加关联线。
|
||||
|
||||
## 注册
|
||||
|
||||
|
||||
@ -7,8 +7,10 @@
|
||||
<blockquote>
|
||||
<p>调整关联线控制点的功能从v0.4.6+开始支持</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>关联性支持文本编辑从v0.5.11+开始支持</p>
|
||||
</blockquote>
|
||||
<p>该插件用于支持添加关联线。</p>
|
||||
<p>该插件目前功能还不完善,不支持在关联线上添加文字。</p>
|
||||
<h2>注册</h2>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map'</span>
|
||||
<span class="hljs-keyword">import</span> AssociativeLine <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/AssociativeLine.js'</span>
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
## 0.5.11
|
||||
|
||||
新增:支持关联性文本编辑。
|
||||
|
||||
优化:优化主题配置更新,改变不涉及节点大小的配置不触发节点重新计算。
|
||||
|
||||
## 0.5.10
|
||||
|
||||
新增:使用LRU缓存算法优化节点复用逻辑。
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.5.11</h2>
|
||||
<p>新增:支持关联性文本编辑。</p>
|
||||
<p>优化:优化主题配置更新,改变不涉及节点大小的配置不触发节点重新计算。</p>
|
||||
<h2>0.5.10</h2>
|
||||
<p>新增:使用LRU缓存算法优化节点复用逻辑。</p>
|
||||
<h2>0.5.10-fix.1</h2>
|
||||
|
||||
@ -55,7 +55,7 @@
|
||||
}
|
||||
```
|
||||
|
||||
`icon`目前只能使用内置的图标,完整图标可以在[icons.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/svg/icons.js)文件中查看。
|
||||
`icon`可以使用内置的图标,完整图标可以在[icons.js](https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/svg/icons.js)文件中查看。也可以扩展图标,参考[扩展图标](https://wanglin2.github.io/mind-map/#/doc/zh/course19/%E6%89%A9%E5%B1%95%E5%9B%BE%E6%A0%87)。
|
||||
|
||||
创建实例时还支持传递其他很多选项参数,完整选项列表可以在[实例化选项](https://wanglin2.github.io/mind-map/#/doc/zh/constructor/%E5%AE%9E%E4%BE%8B%E5%8C%96%E9%80%89%E9%A1%B9)查看。
|
||||
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
<span class="hljs-attr">children</span>: []<span class="hljs-comment">// 子节点</span>
|
||||
}
|
||||
</code></pre>
|
||||
<p><code>icon</code>目前只能使用内置的图标,完整图标可以在<a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/svg/icons.js">icons.js</a>文件中查看。</p>
|
||||
<p><code>icon</code>可以使用内置的图标,完整图标可以在<a href="https://github.com/wanglin2/mind-map/blob/main/simple-mind-map/src/svg/icons.js">icons.js</a>文件中查看。也可以扩展图标,参考<a href="https://wanglin2.github.io/mind-map/#/doc/zh/course19/%E6%89%A9%E5%B1%95%E5%9B%BE%E6%A0%87">扩展图标</a>。</p>
|
||||
<p>创建实例时还支持传递其他很多选项参数,完整选项列表可以在<a href="https://wanglin2.github.io/mind-map/#/doc/zh/constructor/%E5%AE%9E%E4%BE%8B%E5%8C%96%E9%80%89%E9%A1%B9">实例化选项</a>查看。</p>
|
||||
<p>这样得到的思维导图可以通过鼠标和快捷键进行操作,比如单击某个节点可以激活它,双击某个节点可以编辑节点文本,按下<code>Tab</code>键会给当前激活的节点添加一个子节点,按下<code>Enter</code>键会给当前激活的节点添加一个兄弟节点等等,完整的快捷键列表可以参考<a href="https://github.com/wanglin2/mind-map/blob/main/web/src/config/zh.js#L246">快捷键列表</a>。</p>
|
||||
<p>当然有些功能还是需要UI界面的,比如图标列表、编辑超链接等等,需要注意的是<code>simple-mind-map</code>库并不包含UI界面,所以需要你自己开发,然后通过<code>simple-mind-map</code>提供的相关API来操作,本教程的其他章节会向你介绍如何使用。</p>
|
||||
|
||||
@ -295,6 +295,67 @@
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 关联线文字 -->
|
||||
<div class="title noTop">关联线文字</div>
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">字体</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
v-model="style.associativeLineTextFontFamily"
|
||||
placeholder=""
|
||||
@change="update('associativeLineTextFontFamily', $event)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in fontFamilyList"
|
||||
:key="item.value"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
:style="{ fontFamily: item.value }"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">颜色</span>
|
||||
<span
|
||||
class="block"
|
||||
v-popover:popover6
|
||||
:style="{ backgroundColor: style.associativeLineTextColor }"
|
||||
></span>
|
||||
<el-popover ref="popover6" placement="bottom" trigger="click">
|
||||
<Color
|
||||
:color="style.associativeLineTextColor"
|
||||
@change="
|
||||
color => {
|
||||
update('associativeLineTextColor', color)
|
||||
}
|
||||
"
|
||||
></Color>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="rowItem">
|
||||
<span class="name">字号</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 80px"
|
||||
v-model="style.associativeLineTextFontSize"
|
||||
placeholder=""
|
||||
@change="update('associativeLineTextFontSize', $event)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in fontSizeList"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
:style="{ fontSize: item + 'px' }"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 节点边框风格 -->
|
||||
<div class="title noTop">{{ $t('baseStyle.nodeBorderType') }}</div>
|
||||
<div class="row">
|
||||
@ -546,7 +607,7 @@
|
||||
<script>
|
||||
import Sidebar from './Sidebar'
|
||||
import Color from './Color'
|
||||
import { lineWidthList, lineStyleList, backgroundRepeatList, backgroundPositionList, backgroundSizeList } from '@/config'
|
||||
import { lineWidthList, lineStyleList, backgroundRepeatList, backgroundPositionList, backgroundSizeList, fontFamilyList, fontSizeList } from '@/config'
|
||||
import ImgUpload from '@/components/ImgUpload'
|
||||
import { storeConfig } from '@/api'
|
||||
import { mapState, mapMutations } from 'vuex'
|
||||
@ -575,6 +636,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
lineWidthList,
|
||||
fontSizeList,
|
||||
activeTab: 'color',
|
||||
marginActiveTab: 'second',
|
||||
style: {
|
||||
@ -588,6 +650,9 @@ export default {
|
||||
associativeLineWidth: 0,
|
||||
associativeLineActiveWidth: 0,
|
||||
associativeLineActiveColor: '',
|
||||
associativeLineTextFontSize: 0,
|
||||
associativeLineTextColor: '',
|
||||
associativeLineTextFontFamily: '',
|
||||
paddingX: 0,
|
||||
paddingY: 0,
|
||||
imgMaxWidth: 0,
|
||||
@ -636,6 +701,9 @@ export default {
|
||||
backgroundSizeList() {
|
||||
return backgroundSizeList[this.$i18n.locale] || backgroundSizeList.zh
|
||||
},
|
||||
fontFamilyList() {
|
||||
return fontFamilyList[this.$i18n.locale] || fontFamilyList.zh
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
activeSidebar(val) {
|
||||
@ -673,6 +741,9 @@ export default {
|
||||
'associativeLineWidth',
|
||||
'associativeLineActiveWidth',
|
||||
'associativeLineActiveColor',
|
||||
'associativeLineTextFontSize',
|
||||
'associativeLineTextColor',
|
||||
'associativeLineTextFontFamily',
|
||||
'paddingX',
|
||||
'paddingY',
|
||||
'imgMaxWidth',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user