mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-21 10:27:44 +08:00
拉取最新代码
This commit is contained in:
commit
d0e46eb052
12
README.md
12
README.md
@ -103,7 +103,9 @@ const mindMap = new MindMap({
|
||||
|
||||
# 微信交流群
|
||||
|
||||
一群已满,可以扫描如下二维码进入二群,如已过期,可以微信添加`wanglinguanfang`拉你入群。思维导图相关问题皆可在群里提问,不必私聊作者。
|
||||
一群已满,可以扫描如下二维码进入二群,如已过期,可以微信添加`wanglinguanfang`拉你入群。
|
||||
|
||||
大部分问题都可以通过文档解决,所以提问前请确保你已经阅读完了所有文档,文档里没有的可在群里提问,不必私聊作者。
|
||||
|
||||
<img src="./qrcode.jpg" style="width: 300px" />
|
||||
|
||||
@ -469,4 +471,12 @@ const mindMap = new MindMap({
|
||||
<img src="./web/src/assets/avatar/default.png" style="width: 50px;height: 50px;" />
|
||||
<span>晏江</span>
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/default.png" style="width: 50px;height: 50px;" />
|
||||
<span>Eric</span>
|
||||
</span>
|
||||
<span>
|
||||
<img src="./web/src/assets/avatar/Joe.jpg" style="width: 50px;height: 50px;" />
|
||||
<span>Joe</span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
File diff suppressed because one or more lines are too long
2
dist/js/app.js
vendored
2
dist/js/app.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
14
dist/js/chunk-vendors.js
vendored
14
dist/js/chunk-vendors.js
vendored
File diff suppressed because one or more lines are too long
@ -9,7 +9,7 @@
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}</script><link href="dist/css/chunk-vendors.css?b396be756fa41f2b3cf9" rel="stylesheet"><link href="dist/css/app.css?b396be756fa41f2b3cf9" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>const getDataFromBackend = () => {
|
||||
}</script><link href="dist/css/chunk-vendors.css?9c8ee1f3de5ddc8a450e" rel="stylesheet"><link href="dist/css/app.css?9c8ee1f3de5ddc8a450e" rel="stylesheet"></head><body><noscript><strong>We're sorry but thoughts doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script>const getDataFromBackend = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
@ -74,4 +74,4 @@
|
||||
// 可以通过window.$bus.$on()来监听应用的一些事件
|
||||
// 实例化页面
|
||||
window.initApp()
|
||||
}</script><script src="dist/js/chunk-vendors.js?b396be756fa41f2b3cf9"></script><script src="dist/js/app.js?b396be756fa41f2b3cf9"></script></body></html>
|
||||
}</script><script src="dist/js/chunk-vendors.js?9c8ee1f3de5ddc8a450e"></script><script src="dist/js/app.js?9c8ee1f3de5ddc8a450e"></script></body></html>
|
||||
BIN
qrcode.jpg
BIN
qrcode.jpg
Binary file not shown.
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
@ -31,7 +31,7 @@ MindMap.iconList = icons.nodeIconList
|
||||
MindMap.constants = constants
|
||||
MindMap.themes = themes
|
||||
MindMap.defaultTheme = defaultTheme
|
||||
MindMap.version = '0.11.1'
|
||||
MindMap.version = '0.11.2'
|
||||
|
||||
MindMap.usePlugin(MiniMap)
|
||||
.usePlugin(Watermark)
|
||||
|
||||
@ -19,7 +19,8 @@ import {
|
||||
getObjectChangedProps,
|
||||
isUndef,
|
||||
handleGetSvgDataExtraContent,
|
||||
getNodeTreeBoundingRect
|
||||
getNodeTreeBoundingRect,
|
||||
mergeTheme
|
||||
} from './src/utils'
|
||||
import defaultTheme, {
|
||||
checkIsNodeSizeIndependenceConfig
|
||||
@ -34,6 +35,7 @@ class MindMap {
|
||||
* @param {defaultOpt} opt
|
||||
*/
|
||||
constructor(opt = {}) {
|
||||
MindMap.instanceCount++
|
||||
// 合并选项
|
||||
this.opt = this.handleOpt(merge(defaultOpt, opt))
|
||||
// 预处理节点数据
|
||||
@ -252,7 +254,7 @@ class MindMap {
|
||||
// 设置主题
|
||||
initTheme() {
|
||||
// 合并主题配置
|
||||
this.themeConfig = merge(theme[this.opt.theme], this.opt.themeConfig)
|
||||
this.themeConfig = mergeTheme(theme[this.opt.theme], this.opt.themeConfig)
|
||||
// 设置背景样式
|
||||
Style.setBackgroundStyle(this.el, this.themeConfig)
|
||||
}
|
||||
@ -563,8 +565,8 @@ class MindMap {
|
||||
let index = MindMap.hasPlugin(plugin)
|
||||
if (index === -1) {
|
||||
MindMap.usePlugin(plugin, opt)
|
||||
this.initPlugin(plugin)
|
||||
}
|
||||
this.initPlugin(plugin)
|
||||
}
|
||||
|
||||
// 移除插件
|
||||
@ -583,6 +585,7 @@ class MindMap {
|
||||
|
||||
// 实例化插件
|
||||
initPlugin(plugin) {
|
||||
if (this[plugin.instanceName]) return
|
||||
this[plugin.instanceName] = new plugin({
|
||||
mindMap: this,
|
||||
pluginOpt: plugin.pluginOpt
|
||||
@ -616,6 +619,7 @@ class MindMap {
|
||||
this.el.innerHTML = ''
|
||||
this.el = null
|
||||
this.removeCss()
|
||||
MindMap.instanceCount--
|
||||
}
|
||||
}
|
||||
|
||||
@ -632,13 +636,14 @@ MindMap.hasPlugin = plugin => {
|
||||
return item === plugin
|
||||
})
|
||||
}
|
||||
MindMap.instanceCount = 0
|
||||
|
||||
// 定义新主题
|
||||
MindMap.defineTheme = (name, config = {}) => {
|
||||
if (theme[name]) {
|
||||
return new Error('该主题名称已存在')
|
||||
}
|
||||
theme[name] = merge(defaultTheme, config)
|
||||
theme[name] = mergeTheme(defaultTheme, config)
|
||||
}
|
||||
|
||||
export default MindMap
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-mind-map",
|
||||
"version": "0.11.1",
|
||||
"version": "0.11.2",
|
||||
"description": "一个简单的web在线思维导图",
|
||||
"authors": [
|
||||
{
|
||||
|
||||
@ -7,6 +7,8 @@ export const defaultOpt = {
|
||||
el: null,
|
||||
// 思维导图回显数据
|
||||
data: null,
|
||||
// 要恢复的视图数据,一般通过mindMap.view.getTransformData()方法获取
|
||||
viewData: null,
|
||||
// 是否只读
|
||||
readonly: false,
|
||||
// 布局
|
||||
@ -19,6 +21,16 @@ export const defaultOpt = {
|
||||
themeConfig: {},
|
||||
// 放大缩小的增量比例
|
||||
scaleRatio: 0.2,
|
||||
// 平移的步长比例,只在鼠标滚轮和触控板触发的平移中应用
|
||||
translateRatio: 1,
|
||||
// 最小缩小值,百分数,最小为0,该选项只会影响view.narrow方法(影响的行为为Ctrl+-快捷键、鼠标滚轮及触控板),不会影响其他方法,比如view.setScale,所以需要你自行限制大小
|
||||
minZoomRatio: 20,
|
||||
// 最大放大值,百分数,传-1代表不限制,否则传0以上数字,,该选项只会影响view.enlarge方法
|
||||
maxZoomRatio: 400,
|
||||
// 自定义判断wheel事件是否来自电脑的触控板
|
||||
// 默认是通过判断e.deltaY的值是否小于10,显然这种方法是不准确的,当鼠标滚动的很慢,或者触摸移动的很快时判断就失效了,如果你有更好的方法,欢迎提交issue
|
||||
// 如果你希望自己来判断,那么传递一个函数,接收一个参数e(事件对象),需要返回true或false,代表是否是来自触控板
|
||||
customCheckIsTouchPad: null,
|
||||
// 鼠标缩放是否以鼠标当前位置为中心点,否则以画布中心点
|
||||
mouseScaleCenterUseMousePosition: true,
|
||||
// 最多显示几个标签
|
||||
@ -235,6 +247,10 @@ export const defaultOpt = {
|
||||
emptyTextMeasureHeightText: 'abc123我和你',
|
||||
// 是否在进行节点文本编辑时实时更新节点大小和节点位置,开启后当节点数量比较多时可能会造成卡顿
|
||||
openRealtimeRenderOnNodeTextEdit: false,
|
||||
// 默认会给容器元素el绑定mousedown事件,并且会阻止其默认事件,这会带来一定问题,比如你聚焦在思维导图外的其他输入框,点击画布就不会触发其失焦,可以通过该选项关闭阻止。关闭后也会带来一定问题,比如鼠标框选节点时可能会选中节点文字,看你如何取舍
|
||||
mousedownEventPreventDefault: true,
|
||||
// 在激活上粘贴用户剪贴板中的数据时,如果同时存在文本和图片,那么只粘贴文本,忽略图片
|
||||
onlyPasteTextWhenHasImgAndText: true,
|
||||
|
||||
// 【Select插件】
|
||||
// 多选节点时鼠标移动到边缘时的画布移动偏移量
|
||||
@ -318,6 +334,8 @@ export const defaultOpt = {
|
||||
// 导出png、svg、pdf时会获取画布上的svg数据进行克隆,然后通过该克隆的元素进行导出,如果你想对该克隆元素做一些处理,比如新增、替换、修改其中的一些元素,那么可以通过该参数传递一个处理函数,接收svg元素对象,处理后,需要返回原svg元素对象。
|
||||
// 需要注意的是svg对象指的是@svgdotjs/svg.js库的元素对象,所以你需要阅读该库的文档来操作该对象
|
||||
handleBeingExportSvg: null,
|
||||
// 导出图片或pdf都是通过canvas将svg绘制出来,再导出,所以如果思维导图特别大,宽高可能会超出canvas支持的上限,所以会进行缩放,这个上限可以通过该参数设置,代表canvas宽和高的最大宽度
|
||||
maxCanvasSize: 16384,
|
||||
|
||||
// 【AssociativeLine插件】
|
||||
// 关联线默认文字
|
||||
|
||||
@ -156,8 +156,14 @@ class Event extends EventEmitter {
|
||||
// 判断是否是触控板
|
||||
let isTouchPad = false
|
||||
// mac、windows
|
||||
if (e.wheelDeltaY === e.deltaY * -3 || Math.abs(e.wheelDeltaY) <= 10) {
|
||||
isTouchPad = true
|
||||
// if (e.wheelDeltaY === e.deltaY * -3 || Math.abs(e.wheelDeltaY) <= 10) {
|
||||
// isTouchPad = true
|
||||
// }
|
||||
const { customCheckIsTouchPad } = this.mindMap.opt
|
||||
if (typeof customCheckIsTouchPad === 'function') {
|
||||
isTouchPad = customCheckIsTouchPad(e)
|
||||
} else {
|
||||
isTouchPad = Math.abs(e.deltaY) <= 10
|
||||
}
|
||||
this.emit('mousewheel', e, dirs, this, isTouchPad)
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ class Render {
|
||||
this.beingPasteText = ''
|
||||
this.beingPasteImgSize = 0
|
||||
this.currentBeingPasteType = ''
|
||||
this.pasteData = { text: null, img: null}
|
||||
this.pasteData = { text: null, img: null }
|
||||
// 节点高亮框
|
||||
this.highlightBoxNode = null
|
||||
this.highlightBoxNodeStyle = null
|
||||
@ -132,11 +132,6 @@ class Render {
|
||||
}
|
||||
}
|
||||
|
||||
// 解绑事件
|
||||
unBindEvent() {
|
||||
window.removeEventListener('paste', this.handlePaste)
|
||||
}
|
||||
|
||||
// 绑定事件
|
||||
bindEvent() {
|
||||
// 画布点击事件清除当前激活节点列表
|
||||
@ -168,13 +163,14 @@ class Render {
|
||||
})
|
||||
}
|
||||
// 处理非https下的复制黏贴问题
|
||||
if(!navigator.clipboard) {
|
||||
this.handlePaste = this.handlePaste.bind(this)
|
||||
window.addEventListener('paste', this.handlePaste)
|
||||
this.mindMap.on('beforeDestroy', () => {
|
||||
this.unBindEvent()
|
||||
})
|
||||
}
|
||||
// 暂时不启用,因为给页面的其他输入框(比如节点文本编辑框)粘贴内容也会触发,冲突问题暂时没有想到好的解决方法,不可能要求所有输入框都阻止冒泡
|
||||
// if (!navigator.clipboard) {
|
||||
// this.handlePaste = this.handlePaste.bind(this)
|
||||
// window.addEventListener('paste', this.handlePaste)
|
||||
// this.mindMap.on('beforeDestroy', () => {
|
||||
// window.removeEventListener('paste', this.handlePaste)
|
||||
// })
|
||||
// }
|
||||
}
|
||||
|
||||
// 性能模式,懒加载节点
|
||||
@ -419,7 +415,7 @@ class Render {
|
||||
this.mindMap.keyCommand.addShortcut('Control+Down', () => {
|
||||
this.mindMap.execCommand('DOWN_NODE')
|
||||
})
|
||||
// 复制节点、
|
||||
// 复制节点
|
||||
this.mindMap.keyCommand.addShortcut('Control+c', () => {
|
||||
this.copy()
|
||||
})
|
||||
@ -429,7 +425,7 @@ class Render {
|
||||
})
|
||||
// 粘贴节点
|
||||
this.mindMap.keyCommand.addShortcut('Control+v', () => {
|
||||
if(navigator.clipboard) this.paste()
|
||||
if (navigator.clipboard) this.paste()
|
||||
})
|
||||
// 根节点居中显示
|
||||
this.mindMap.keyCommand.addShortcut('Control+Enter', () => {
|
||||
@ -1133,23 +1129,24 @@ class Render {
|
||||
}
|
||||
|
||||
// 非https下复制黏贴,获取内容方法
|
||||
handlePaste(event){
|
||||
const clipboardData = event.clipboardData || event.originalEvent.clipboardData || window.clipboardData
|
||||
handlePaste(event) {
|
||||
const { disabledClipboard } = this.mindMap.opt
|
||||
if (disabledClipboard) return
|
||||
const clipboardData =
|
||||
event.clipboardData || event.originalEvent.clipboardData
|
||||
const items = clipboardData.items
|
||||
const clipboardType = items && items.length ? items[0].type : ''
|
||||
const isImg = clipboardType.indexOf('image') > -1
|
||||
const isText = clipboardType.indexOf('text') > -1
|
||||
this.pasteData = { img: null, text: null}
|
||||
|
||||
// 复制的图片处理逻辑
|
||||
if (isImg) {
|
||||
for (let index in items) {
|
||||
const item = items[index]
|
||||
if (item.kind === 'file') this.pasteData.img = item.getAsFile()
|
||||
let img = null
|
||||
let text = ''
|
||||
Array.from(items).forEach(item => {
|
||||
if (item.type.indexOf('image') > -1) {
|
||||
img = item.getAsFile()
|
||||
}
|
||||
}
|
||||
// 复制的文本处理逻辑
|
||||
if (isText) this.pasteData.text = clipboardData.getData('text')
|
||||
if (item.type.indexOf('text') > -1) {
|
||||
text = clipboardData.getData('text')
|
||||
}
|
||||
})
|
||||
this.pasteData.img = img
|
||||
this.pasteData.text = text
|
||||
this.paste()
|
||||
}
|
||||
|
||||
@ -1159,14 +1156,17 @@ class Render {
|
||||
errorHandler,
|
||||
handleIsSplitByWrapOnPasteCreateNewNode,
|
||||
handleNodePasteImg,
|
||||
disabledClipboard
|
||||
disabledClipboard,
|
||||
onlyPasteTextWhenHasImgAndText
|
||||
} = this.mindMap.opt
|
||||
// 读取剪贴板的文字和图片
|
||||
let text = ''
|
||||
let img = null
|
||||
if (!disabledClipboard) {
|
||||
try {
|
||||
const res = navigator.clipboard ? await getDataFromClipboard() : this.pasteData
|
||||
const res = navigator.clipboard
|
||||
? await getDataFromClipboard()
|
||||
: this.pasteData
|
||||
text = res.text || ''
|
||||
img = res.img || null
|
||||
} catch (error) {
|
||||
@ -1262,7 +1262,7 @@ class Render {
|
||||
}
|
||||
}
|
||||
// 存在图片,则添加到当前激活节点
|
||||
if (img) {
|
||||
if (img && (!text || !onlyPasteTextWhenHasImgAndText)) {
|
||||
try {
|
||||
let imgData = null
|
||||
// 自定义图片处理函数
|
||||
@ -1600,7 +1600,7 @@ class Render {
|
||||
this.setNodeDataRender(node, data)
|
||||
// 更新了连线的样式
|
||||
if (lineStyleProps.includes(prop)) {
|
||||
(node.parent || node).renderLine(true)
|
||||
;(node.parent || node).renderLine(true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1621,7 +1621,7 @@ class Render {
|
||||
}
|
||||
})
|
||||
if (hasLineStyleProps) {
|
||||
(node.parent || node).renderLine(true)
|
||||
;(node.parent || node).renderLine(true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1180,10 +1180,9 @@ class MindMapNode {
|
||||
|
||||
// 获取padding值
|
||||
getPaddingVale() {
|
||||
let { isActive } = this.getData()
|
||||
return {
|
||||
paddingX: this.getStyle('paddingX', true, isActive),
|
||||
paddingY: this.getStyle('paddingY', true, isActive)
|
||||
paddingX: this.getStyle('paddingX'),
|
||||
paddingY: this.getStyle('paddingY')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { checkIsNodeStyleDataKey } from '../../../utils/index'
|
||||
|
||||
const rootProp = ['paddingX', 'paddingY']
|
||||
const backgroundStyleProps = [
|
||||
'backgroundColor',
|
||||
'backgroundImage',
|
||||
@ -62,11 +61,10 @@ class Style {
|
||||
// 合并样式
|
||||
merge(prop, root) {
|
||||
let themeConfig = this.ctx.mindMap.themeConfig
|
||||
// 三级及以下节点
|
||||
let defaultConfig = themeConfig.node
|
||||
let defaultConfig = null
|
||||
let useRoot = false
|
||||
if (root || rootProp.includes(prop)) {
|
||||
// 直接使用最外层样式
|
||||
if (root) {
|
||||
// 使用最外层样式
|
||||
useRoot = true
|
||||
defaultConfig = themeConfig
|
||||
} else if (this.ctx.isGeneralization) {
|
||||
@ -78,12 +76,21 @@ class Style {
|
||||
} else if (this.ctx.layerIndex === 1) {
|
||||
// 二级节点
|
||||
defaultConfig = themeConfig.second
|
||||
} else {
|
||||
// 三级及以下节点
|
||||
defaultConfig = themeConfig.node
|
||||
}
|
||||
let value = ''
|
||||
// 优先使用节点本身的样式
|
||||
const value =
|
||||
this.getSelfStyle(prop) !== undefined
|
||||
? this.getSelfStyle(prop)
|
||||
: defaultConfig[prop]
|
||||
if (this.getSelfStyle(prop) !== undefined) {
|
||||
value = this.getSelfStyle(prop)
|
||||
} else if (defaultConfig[prop] !== undefined) {
|
||||
// 否则使用对应层级的样式
|
||||
value = defaultConfig[prop]
|
||||
} else {
|
||||
// 否则使用最外层样式
|
||||
value = themeConfig[prop]
|
||||
}
|
||||
if (!useRoot) {
|
||||
this.addToEffectiveStyles({
|
||||
[prop]: value
|
||||
@ -348,8 +355,10 @@ class Style {
|
||||
|
||||
// hover和激活节点
|
||||
hoverNode(node) {
|
||||
const hoverRectColor = this.merge('hoverRectColor') || this.ctx.mindMap.opt.hoverRectColor
|
||||
node.radius(5).fill('none').stroke({
|
||||
const hoverRectColor =
|
||||
this.merge('hoverRectColor') || this.ctx.mindMap.opt.hoverRectColor
|
||||
const hoverRectRadius = this.merge('hoverRectRadius')
|
||||
node.radius(hoverRectRadius).fill('none').stroke({
|
||||
color: hoverRectColor
|
||||
})
|
||||
}
|
||||
|
||||
@ -30,8 +30,11 @@ class View {
|
||||
})
|
||||
// 拖动视图
|
||||
this.mindMap.event.on('mousedown', e => {
|
||||
if (this.mindMap.opt.isDisableDrag) return
|
||||
e.preventDefault()
|
||||
const { isDisableDrag, mousedownEventPreventDefault } = this.mindMap.opt
|
||||
if (isDisableDrag) return
|
||||
if (mousedownEventPreventDefault) {
|
||||
e.preventDefault()
|
||||
}
|
||||
this.sx = this.x
|
||||
this.sy = this.y
|
||||
})
|
||||
@ -63,7 +66,8 @@ class View {
|
||||
mouseScaleCenterUseMousePosition,
|
||||
mousewheelMoveStep,
|
||||
mousewheelZoomActionReverse,
|
||||
disableMouseWheelZoom
|
||||
disableMouseWheelZoom,
|
||||
translateRatio
|
||||
} = this.mindMap.opt
|
||||
// 是否自定义鼠标滚轮事件
|
||||
if (
|
||||
@ -138,7 +142,7 @@ class View {
|
||||
if (dirs.includes(CONSTANTS.DIR.RIGHT)) {
|
||||
mx = -stepX
|
||||
}
|
||||
this.translateXY(mx, my)
|
||||
this.translateXY(mx * translateRatio, my * translateRatio)
|
||||
}
|
||||
})
|
||||
this.mindMap.on('resize', () => {
|
||||
@ -246,8 +250,9 @@ class View {
|
||||
|
||||
// 缩小
|
||||
narrow(cx, cy, isTouchPad) {
|
||||
const scaleRatio = this.mindMap.opt.scaleRatio / (isTouchPad ? 5 : 1)
|
||||
const scale = Math.max(this.scale - scaleRatio, 0.1)
|
||||
let { scaleRatio, minZoomRatio } = this.mindMap.opt
|
||||
scaleRatio = scaleRatio / (isTouchPad ? 5 : 1)
|
||||
const scale = Math.max(this.scale - scaleRatio, minZoomRatio / 100)
|
||||
this.scaleInCenter(scale, cx, cy)
|
||||
this.transform()
|
||||
this.emitEvent('scale')
|
||||
@ -255,8 +260,14 @@ class View {
|
||||
|
||||
// 放大
|
||||
enlarge(cx, cy, isTouchPad) {
|
||||
const scaleRatio = this.mindMap.opt.scaleRatio / (isTouchPad ? 5 : 1)
|
||||
const scale = this.scale + scaleRatio
|
||||
let { scaleRatio, maxZoomRatio } = this.mindMap.opt
|
||||
scaleRatio = scaleRatio / (isTouchPad ? 5 : 1)
|
||||
let scale = 0
|
||||
if (maxZoomRatio === -1) {
|
||||
scale = this.scale + scaleRatio
|
||||
} else {
|
||||
scale = Math.min(this.scale + scaleRatio, maxZoomRatio / 100)
|
||||
}
|
||||
this.scaleInCenter(scale, cx, cy)
|
||||
this.transform()
|
||||
this.emitEvent('scale')
|
||||
|
||||
@ -244,7 +244,9 @@ class Base {
|
||||
isResizeSource ||
|
||||
(newData && JSON.stringify(oldData) !== JSON.stringify(newData))
|
||||
) {
|
||||
gNode.nodeData.data = newData
|
||||
if (newData) {
|
||||
gNode.nodeData.data = newData
|
||||
}
|
||||
gNode.getSize()
|
||||
gNode.needLayout = true
|
||||
}
|
||||
|
||||
@ -129,6 +129,7 @@ class Export {
|
||||
|
||||
// svg转png
|
||||
svgToPng(svgSrc, transparent, clipData = null) {
|
||||
const { maxCanvasSize, minExportImgCanvasScale } = this.mindMap.opt
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image()
|
||||
// 跨域图片需要添加这个属性,否则画布被污染了无法导出图片
|
||||
@ -136,10 +137,7 @@ class Export {
|
||||
img.onload = async () => {
|
||||
try {
|
||||
const canvas = document.createElement('canvas')
|
||||
const dpr = Math.max(
|
||||
window.devicePixelRatio,
|
||||
this.mindMap.opt.minExportImgCanvasScale
|
||||
)
|
||||
const dpr = Math.max(window.devicePixelRatio, minExportImgCanvasScale)
|
||||
let imgWidth = img.width
|
||||
let imgHeight = img.height
|
||||
// 如果是裁减操作的话,那么需要手动添加内边距,及调整图片大小为实际的裁减区域的大小,不要忘了内边距哦
|
||||
@ -152,29 +150,40 @@ class Export {
|
||||
imgHeight = clipData.height + paddingY * 2
|
||||
}
|
||||
// 检查是否超出canvas支持的像素上限
|
||||
const maxSize = 16384 / dpr
|
||||
const maxArea = maxSize * maxSize
|
||||
if (imgWidth * imgHeight > maxArea) {
|
||||
// canvas大小需要乘以dpr
|
||||
let canvasWidth = imgWidth * dpr
|
||||
let canvasHeight = imgHeight * dpr
|
||||
if (canvasWidth > maxCanvasSize || canvasHeight > maxCanvasSize) {
|
||||
let newWidth = null
|
||||
let newHeight = null
|
||||
if (imgWidth > maxSize) {
|
||||
newWidth = maxArea / imgHeight
|
||||
} else if (imgHeight > maxSize) {
|
||||
newHeight = maxArea / imgWidth
|
||||
if (canvasWidth > maxCanvasSize) {
|
||||
// 如果宽度超出限制,那么调整为上限值
|
||||
newWidth = maxCanvasSize
|
||||
} else if (canvasHeight > maxCanvasSize) {
|
||||
// 高度同理
|
||||
newHeight = maxCanvasSize
|
||||
}
|
||||
const res = resizeImgSize(imgWidth, imgHeight, newWidth, newHeight)
|
||||
imgWidth = res[0]
|
||||
imgHeight = res[1]
|
||||
// 计算缩放后的宽高
|
||||
const res = resizeImgSize(
|
||||
canvasWidth,
|
||||
canvasHeight,
|
||||
newWidth,
|
||||
newHeight
|
||||
)
|
||||
canvasWidth = res[0]
|
||||
canvasHeight = res[1]
|
||||
}
|
||||
canvas.width = imgWidth * dpr
|
||||
canvas.height = imgHeight * dpr
|
||||
canvas.style.width = imgWidth + 'px'
|
||||
canvas.style.height = imgHeight + 'px'
|
||||
canvas.width = canvasWidth
|
||||
canvas.height = canvasHeight
|
||||
const styleWidth = canvasWidth / dpr
|
||||
const styleHeight = canvasHeight / dpr
|
||||
canvas.style.width = styleWidth + 'px'
|
||||
canvas.style.height = styleHeight + 'px'
|
||||
const ctx = canvas.getContext('2d')
|
||||
ctx.scale(dpr, dpr)
|
||||
// 绘制背景
|
||||
if (!transparent) {
|
||||
await this.drawBackgroundToCanvas(ctx, imgWidth, imgHeight)
|
||||
await this.drawBackgroundToCanvas(ctx, styleWidth, styleHeight)
|
||||
}
|
||||
// 图片绘制到canvas里
|
||||
// 如果有裁减数据,那么需要进行裁减
|
||||
@ -191,7 +200,7 @@ class Export {
|
||||
clipData.height
|
||||
)
|
||||
} else {
|
||||
ctx.drawImage(img, 0, 0, imgWidth, imgHeight)
|
||||
ctx.drawImage(img, 0, 0, styleWidth, styleHeight)
|
||||
}
|
||||
resolve(canvas.toDataURL())
|
||||
} catch (error) {
|
||||
|
||||
@ -3,6 +3,9 @@ import Quill from 'quill'
|
||||
import { getChromeVersion, htmlEscape } from '../utils/index'
|
||||
import { getBaseStyleText, getFontStyleText } from './FormulaStyle'
|
||||
|
||||
let extended = false
|
||||
const QuillFormula = Quill.import('formats/formula')
|
||||
|
||||
// 数学公式支持插件
|
||||
// 该插件在富文本模式下可用
|
||||
class Formula {
|
||||
@ -16,6 +19,18 @@ class Formula {
|
||||
this.cssEl = null
|
||||
this.addStyle()
|
||||
this.extendQuill()
|
||||
this.onDestroy = this.onDestroy.bind(this)
|
||||
this.mindMap.on('beforeDestroy', this.onDestroy)
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
const instanceCount = Object.getPrototypeOf(this.mindMap).constructor
|
||||
.instanceCount
|
||||
// 如果思维导图实例数量变成0了,那么就恢复成默认的
|
||||
if (instanceCount <= 1) {
|
||||
extended = false
|
||||
Quill.register('formats/formula', QuillFormula, true)
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
@ -50,7 +65,9 @@ class Formula {
|
||||
|
||||
// 修改formula格式工具
|
||||
extendQuill() {
|
||||
const QuillFormula = Quill.import('formats/formula')
|
||||
if (extended) return
|
||||
extended = true
|
||||
|
||||
const self = this
|
||||
|
||||
class CustomFormulaBlot extends QuillFormula {
|
||||
@ -168,11 +185,13 @@ class Formula {
|
||||
// 插件被移除前做的事情
|
||||
beforePluginRemove() {
|
||||
this.removeStyle()
|
||||
this.mindMap.off('beforeDestroy', this.onDestroy)
|
||||
}
|
||||
|
||||
// 插件被卸载前做的事情
|
||||
beforePluginDestroy() {
|
||||
this.removeStyle()
|
||||
this.mindMap.off('beforeDestroy', this.onDestroy)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -549,6 +549,20 @@ class RichText {
|
||||
delta.ops = ops
|
||||
return delta
|
||||
})
|
||||
// 拦截图片的粘贴
|
||||
this.quill.root.addEventListener(
|
||||
'paste',
|
||||
e => {
|
||||
if (
|
||||
e.clipboardData &&
|
||||
e.clipboardData.files &&
|
||||
e.clipboardData.files.length
|
||||
) {
|
||||
e.preventDefault()
|
||||
}
|
||||
},
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
// 获取粘贴的文本的样式
|
||||
|
||||
@ -224,9 +224,15 @@ class Search {
|
||||
replaceText = String(replaceText)
|
||||
let currentNode = this.matchNodeList[this.currentIndex]
|
||||
if (!currentNode) return
|
||||
let text = this.getReplacedText(currentNode, this.searchText, replaceText)
|
||||
// 如果当前搜索文本是替换文本的子串,那么该节点还是符合搜索结果的
|
||||
const keep = replaceText.includes(this.searchText)
|
||||
const text = this.getReplacedText(currentNode, this.searchText, replaceText)
|
||||
this.notResetSearchText = true
|
||||
currentNode.setText(text, currentNode.getData('richText'), true)
|
||||
if (keep) {
|
||||
this.updateMatchNodeList(this.matchNodeList)
|
||||
return
|
||||
}
|
||||
const newList = this.matchNodeList.filter(node => {
|
||||
return currentNode !== node
|
||||
})
|
||||
@ -249,6 +255,8 @@ class Search {
|
||||
)
|
||||
return
|
||||
replaceText = String(replaceText)
|
||||
// 如果当前搜索文本是替换文本的子串,那么该节点还是符合搜索结果的
|
||||
const keep = replaceText.includes(this.searchText)
|
||||
this.matchNodeList.forEach(node => {
|
||||
const text = this.getReplacedText(node, this.searchText, replaceText)
|
||||
if (this.isNodeInstance(node)) {
|
||||
@ -267,7 +275,11 @@ class Search {
|
||||
})
|
||||
this.mindMap.render()
|
||||
this.mindMap.command.addHistory()
|
||||
this.endSearch()
|
||||
if (keep) {
|
||||
this.updateMatchNodeList(this.matchNodeList)
|
||||
} else {
|
||||
this.endSearch()
|
||||
}
|
||||
}
|
||||
|
||||
// 获取某个节点替换后的文本
|
||||
|
||||
@ -41,7 +41,8 @@ class Select {
|
||||
|
||||
// 鼠标按下
|
||||
onMousedown(e) {
|
||||
if (this.mindMap.opt.readonly) {
|
||||
const { readonly, mousedownEventPreventDefault } = this.mindMap.opt
|
||||
if (readonly) {
|
||||
return
|
||||
}
|
||||
let { useLeftKeySelectionRightKeyDrag } = this.mindMap.opt
|
||||
@ -51,7 +52,9 @@ class Select {
|
||||
) {
|
||||
return
|
||||
}
|
||||
e.preventDefault()
|
||||
if (mousedownEventPreventDefault) {
|
||||
e.preventDefault()
|
||||
}
|
||||
this.isMousedown = true
|
||||
this.cacheActiveList = [...this.mindMap.renderer.activeNodeList]
|
||||
let { x, y } = this.mindMap.toPos(e.clientX, e.clientY)
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 秋天
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 背景颜色
|
||||
backgroundColor: '#fff2df',
|
||||
// 连线的颜色
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 牛油果
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 背景颜色
|
||||
backgroundColor: '#e6f1de',
|
||||
// 连线的颜色
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 黑金
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(18, 20, 20)',
|
||||
// 连线的颜色
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 黑色幽默
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(27, 31, 34)',
|
||||
// 连线的颜色
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 天空蓝
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(115, 161, 191)',
|
||||
// 背景颜色
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 脑残粉
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(191, 115, 148)',
|
||||
// 背景颜色
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 脑图经典
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: '#fff',
|
||||
// 连线的粗细
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 经典2
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(51, 51, 51)',
|
||||
// 连线的粗细
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 经典3
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(94, 202, 110)',
|
||||
// 连线的粗细
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 经典4
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(30, 53, 86)',
|
||||
// 连线的粗细
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 经典蓝
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(51, 51, 51)',
|
||||
// 连线的粗细
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 经典绿
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(123, 199, 120)',
|
||||
// 背景颜色
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 咖啡
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(173, 123, 91)',
|
||||
lineWidth: 4,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 课程绿
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(113, 195, 169)',
|
||||
lineWidth: 3,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 暗色
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(17, 68, 23)',
|
||||
// 连线的粗细
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 暗色2
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(75, 81, 78)',
|
||||
lineWidth: 3,
|
||||
|
||||
@ -87,7 +87,11 @@ export default {
|
||||
// 连线标记的位置,start(头部)、end(尾部),该配置在showLineMarker配置为true时生效
|
||||
lineMarkerDir: 'end',
|
||||
// 节点鼠标hover和激活时显示的矩形边框的颜色,主题里不设置,默认会取hoverRectColor实例化选项的值
|
||||
hoverRectColor: ''
|
||||
hoverRectColor: '',
|
||||
// 点鼠标hover和激活时显示的矩形边框的圆角大小
|
||||
hoverRectRadius: 5
|
||||
// paddingX: 15,
|
||||
// paddingY: 5
|
||||
},
|
||||
// 二级节点样式
|
||||
second: {
|
||||
@ -112,7 +116,10 @@ export default {
|
||||
startDir: [0, 0],
|
||||
endDir: [1, 0],
|
||||
lineMarkerDir: 'end',
|
||||
hoverRectColor: ''
|
||||
hoverRectColor: '',
|
||||
hoverRectRadius: 5
|
||||
// paddingX: 15,
|
||||
// paddingY: 5
|
||||
},
|
||||
// 三级及以下节点样式
|
||||
node: {
|
||||
@ -137,7 +144,10 @@ export default {
|
||||
startDir: [0, 0],
|
||||
endDir: [1, 0],
|
||||
lineMarkerDir: 'end',
|
||||
hoverRectColor: ''
|
||||
hoverRectColor: '',
|
||||
hoverRectRadius: 5
|
||||
// paddingX: 15,
|
||||
// paddingY: 5
|
||||
},
|
||||
// 概要节点样式
|
||||
generalization: {
|
||||
@ -161,7 +171,10 @@ export default {
|
||||
endColor: '#fff',
|
||||
startDir: [0, 0],
|
||||
endDir: [1, 0],
|
||||
hoverRectColor: ''
|
||||
hoverRectColor: '',
|
||||
hoverRectRadius: 5
|
||||
// paddingX: 15,
|
||||
// paddingY: 5
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,7 +208,8 @@ const nodeSizeIndependenceList = [
|
||||
'endColor',
|
||||
'startDir',
|
||||
'endDir',
|
||||
'hoverRectColor'
|
||||
'hoverRectColor',
|
||||
'hoverRectRadius'
|
||||
]
|
||||
export const checkIsNodeSizeIndependenceConfig = config => {
|
||||
let keys = Object.keys(config)
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 泥土黄
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(191, 147, 115)',
|
||||
// 背景颜色
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 清新绿
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: '#333',
|
||||
// 背景颜色
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 清新红
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(191, 115, 115)',
|
||||
// 背景颜色
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 金色vip
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(51, 56, 62)',
|
||||
lineWidth: 3,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 绿叶
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(40, 193, 84)',
|
||||
lineWidth: 3,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 深夜办公室
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(32, 37, 49)',
|
||||
// 连线的颜色
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 小黄人
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(51, 51, 51)',
|
||||
lineWidth: 3,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 薄荷
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(104, 204, 202)',
|
||||
lineWidth: 3,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 橙汁
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 背景颜色
|
||||
backgroundColor: '#070616',
|
||||
// 连线的颜色
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 粉红葡萄
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(166, 101, 106)',
|
||||
lineWidth: 3,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 红色精神
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 背景颜色
|
||||
backgroundColor: 'rgb(255, 238, 228)',
|
||||
// 连线的颜色
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 浪漫紫
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(123, 115, 191)',
|
||||
// 背景颜色
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 简约黑
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(34, 34, 34)',
|
||||
lineWidth: 4,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 天清绿
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: '#fff',
|
||||
lineWidth: 3,
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import defaultTheme from './default'
|
||||
import merge from 'deepmerge'
|
||||
import { mergeTheme } from '../utils'
|
||||
|
||||
// 活力橙
|
||||
export default merge(defaultTheme, {
|
||||
export default mergeTheme(defaultTheme, {
|
||||
// 连线的颜色
|
||||
lineColor: 'rgb(254, 146, 0)',
|
||||
lineWidth: 3,
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
} from '../constants/constant'
|
||||
import MersenneTwister from './mersenneTwister'
|
||||
import { ForeignObject } from '@svgdotjs/svg.js'
|
||||
import merge from 'deepmerge'
|
||||
|
||||
// 深度优先遍历树
|
||||
export const walk = (
|
||||
@ -1610,3 +1611,12 @@ export const sortNodeList = nodeList => {
|
||||
})
|
||||
return nodeList
|
||||
}
|
||||
|
||||
// 合并主题配置
|
||||
export const mergeTheme = (dest, source) => {
|
||||
return merge(dest, source, {
|
||||
arrayMerge: (destinationArray, sourceArray) => {
|
||||
return sourceArray
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
BIN
web/src/assets/avatar/Joe.jpg
Normal file
BIN
web/src/assets/avatar/Joe.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
@ -111,7 +111,8 @@ export default {
|
||||
copyToPng: 'Png',
|
||||
copySuccess: 'Copy success',
|
||||
copyFail: 'Copy fail',
|
||||
number: 'Number child nodes'
|
||||
number: 'Number child nodes',
|
||||
expandNodeChild: 'Expand all sub nodes'
|
||||
},
|
||||
count: {
|
||||
words: 'Words',
|
||||
|
||||
@ -111,7 +111,8 @@ export default {
|
||||
copyToPng: '图片',
|
||||
copySuccess: '复制成功',
|
||||
copyFail: '复制失败',
|
||||
number: '编号其子节点'
|
||||
number: '编号其子节点',
|
||||
expandNodeChild: '展开所有下级节点'
|
||||
},
|
||||
count: {
|
||||
words: '字数',
|
||||
|
||||
@ -111,7 +111,8 @@ export default {
|
||||
copyToPng: '圖片',
|
||||
copySuccess: '複製成功',
|
||||
copyFail: '複製失敗',
|
||||
number: '將其子節點編號'
|
||||
number: '將其子節點編號',
|
||||
expandNodeChild: '展開所有下級節點'
|
||||
},
|
||||
count: {
|
||||
words: '字數',
|
||||
|
||||
@ -56,6 +56,9 @@
|
||||
<span class="name">{{ $t('contextmenu.moveDownNode') }}</span>
|
||||
<span class="desc">Ctrl + ↓</span>
|
||||
</div>
|
||||
<div class="item" @click="exec('EXPAND_ALL')">
|
||||
<span class="name">{{ $t('contextmenu.expandNodeChild') }}</span>
|
||||
</div>
|
||||
<div class="item" v-if="supportNumbers">
|
||||
<span class="name">{{ $t('contextmenu.number') }}</span>
|
||||
<span class="el-icon-arrow-right"></span>
|
||||
@ -344,12 +347,11 @@ export default {
|
||||
|
||||
// 计算右键菜单元素的显示位置
|
||||
getShowPosition(x, y) {
|
||||
this.subItemsShowLeft = false
|
||||
const rect = this.$refs.contextmenuRef.getBoundingClientRect()
|
||||
if (x + rect.width > window.innerWidth) {
|
||||
x = x - rect.width - 20
|
||||
this.subItemsShowLeft = true
|
||||
}
|
||||
this.subItemsShowLeft = x + rect.width + 150 > window.innerWidth
|
||||
if (y + rect.height > window.innerHeight) {
|
||||
y = window.innerHeight - rect.height - 10
|
||||
}
|
||||
@ -462,6 +464,9 @@ export default {
|
||||
this.node
|
||||
)
|
||||
break
|
||||
case 'EXPAND_ALL':
|
||||
this.$bus.$emit('execCommand', key, this.node.uid)
|
||||
break
|
||||
default:
|
||||
this.$bus.$emit('execCommand', key, ...args)
|
||||
break
|
||||
|
||||
@ -124,8 +124,8 @@ export default {
|
||||
node.setImage({
|
||||
url: img || 'none',
|
||||
title: this.imgTitle,
|
||||
width: res.width,
|
||||
height: res.height
|
||||
width: res.width || 100,
|
||||
height: res.height || 100
|
||||
})
|
||||
})
|
||||
this.cancel()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user