'基本完成'
@ -793,8 +793,8 @@ export default {
|
||||
// 自定义配置...
|
||||
}
|
||||
},
|
||||
"layout": "logicalStructure",
|
||||
// "layout": "mindMap",
|
||||
// "layout": "logicalStructure"
|
||||
// "layout": "catalogOrganization"
|
||||
"layout": "organizationStructure"
|
||||
// "layout": "organizationStructure"
|
||||
}
|
||||
@ -9,6 +9,9 @@ import Command from './src/Command'
|
||||
import BatchExecution from './src/BatchExecution'
|
||||
import Export from './src/Export'
|
||||
import Select from './src/Select'
|
||||
import {
|
||||
layoutValueList
|
||||
} from './src/utils/constant'
|
||||
import {
|
||||
SVG
|
||||
} from '@svgdotjs/svg.js'
|
||||
@ -32,7 +35,11 @@ const defaultOpt = {
|
||||
// 节点里图片和文字的间距
|
||||
imgTextMargin: 5,
|
||||
// 节点里各种文字信息的间距,如图标和文字的间距
|
||||
textContentMargin: 2
|
||||
textContentMargin: 2,
|
||||
// 多选节点时鼠标移动到边缘时的画布移动偏移量
|
||||
selectTranslateStep: 3,
|
||||
// 多选节点时鼠标移动距边缘多少距离时开始偏移
|
||||
selectTranslateLimit: 20
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,7 +130,7 @@ class MindMap {
|
||||
*/
|
||||
handleOpt(opt) {
|
||||
// 检查布局配置
|
||||
if (!['logicalStructure', 'mindMap', 'catalogOrganization', 'organizationStructure'].includes(opt.layout)) {
|
||||
if (!layoutValueList.includes(opt.layout)) {
|
||||
opt.layout = 'logicalStructure'
|
||||
}
|
||||
// 检查主题配置
|
||||
@ -248,6 +255,32 @@ class MindMap {
|
||||
return prop === undefined ? this.themeConfig : this.themeConfig[prop]
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-07-13 16:17:06
|
||||
* @Desc: 获取当前布局结构
|
||||
*/
|
||||
getLayout() {
|
||||
return this.opt.layout
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-07-13 16:17:33
|
||||
* @Desc: 设置布局结构
|
||||
*/
|
||||
setLayout(layout) {
|
||||
// 检查布局配置
|
||||
if (!layoutValueList.includes(layout)) {
|
||||
layout = 'logicalStructure'
|
||||
}
|
||||
this.opt.layout = layout
|
||||
this.renderer.setLayout()
|
||||
this.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-05-04 13:01:00
|
||||
@ -262,7 +295,7 @@ class MindMap {
|
||||
* @Date: 2021-07-01 22:06:38
|
||||
* @Desc: 导出
|
||||
*/
|
||||
async export(...args) {
|
||||
async export (...args) {
|
||||
let result = await this.doExport.export(...args)
|
||||
return result
|
||||
}
|
||||
|
||||
@ -78,15 +78,13 @@ class Node {
|
||||
textContentHeight: 0
|
||||
}
|
||||
// 各种文字信息的间距
|
||||
this._textContentItemMargin = this.mindMap.opt.textContentMargin
|
||||
this.textContentItemMargin = this.mindMap.opt.textContentMargin
|
||||
// 图片和文字节点的间距
|
||||
this._blockContentMargin = this.mindMap.opt.imgTextMargin
|
||||
this.blockContentMargin = this.mindMap.opt.imgTextMargin
|
||||
// 展开收缩按钮尺寸
|
||||
this._expandBtnSize = this.mindMap.opt.expandBtnSize
|
||||
this.expandBtnSize = this.mindMap.opt.expandBtnSize
|
||||
// 初始渲染
|
||||
this._initRender = true
|
||||
// 更新的时候的钩子
|
||||
this.updateHooks = []
|
||||
this.initRender = true
|
||||
// 初始化
|
||||
this.createNodeData()
|
||||
this.getSize()
|
||||
@ -241,7 +239,7 @@ class Node {
|
||||
if (this._iconData.length > 0) {
|
||||
textContentWidth += this._iconData.reduce((sum, cur) => {
|
||||
textContentHeight = Math.max(textContentHeight, cur.height)
|
||||
return sum += cur.width + this._textContentItemMargin
|
||||
return sum += cur.width + this.textContentItemMargin
|
||||
}, 0)
|
||||
}
|
||||
// 文字
|
||||
@ -258,7 +256,7 @@ class Node {
|
||||
if (this._tagData.length > 0) {
|
||||
textContentWidth += this._tagData.reduce((sum, cur) => {
|
||||
textContentHeight = Math.max(textContentHeight, cur.height)
|
||||
return sum += cur.width + this._textContentItemMargin
|
||||
return sum += cur.width + this.textContentItemMargin
|
||||
}, 0)
|
||||
}
|
||||
// 备注
|
||||
@ -270,7 +268,7 @@ class Node {
|
||||
this._rectInfo.textContentWidth = textContentWidth
|
||||
this._rectInfo.textContentHeight = textContentHeight
|
||||
// 间距
|
||||
let margin = imgContentHeight > 0 && textContentHeight > 0 ? this._blockContentMargin : 0
|
||||
let margin = imgContentHeight > 0 && textContentHeight > 0 ? this.blockContentMargin : 0
|
||||
let { paddingX, paddingY } = this.getPaddingVale()
|
||||
return {
|
||||
width: Math.max(imgContentWidth, textContentWidth) + paddingX * 2,
|
||||
@ -481,7 +479,7 @@ class Node {
|
||||
let {
|
||||
width,
|
||||
height,
|
||||
_textContentItemMargin
|
||||
textContentItemMargin
|
||||
} = this
|
||||
let { paddingY } = this.getPaddingVale()
|
||||
// 创建组
|
||||
@ -507,7 +505,7 @@ class Node {
|
||||
this._iconData.forEach((item) => {
|
||||
item.node.x(textContentOffsetX + iconLeft).y((this._rectInfo.textContentHeight - item.height) / 2)
|
||||
iconNested.add(item.node)
|
||||
iconLeft += item.width + _textContentItemMargin
|
||||
iconLeft += item.width + textContentItemMargin
|
||||
})
|
||||
textContentNested.add(iconNested)
|
||||
textContentOffsetX += iconLeft
|
||||
@ -516,13 +514,13 @@ class Node {
|
||||
if (this._textData) {
|
||||
this._textData.node.x(textContentOffsetX).y(0)
|
||||
textContentNested.add(this._textData.node)
|
||||
textContentOffsetX += this._textData.width + _textContentItemMargin
|
||||
textContentOffsetX += this._textData.width + textContentItemMargin
|
||||
}
|
||||
// 超链接
|
||||
if (this._hyperlinkData) {
|
||||
this._hyperlinkData.node.x(textContentOffsetX).y((this._rectInfo.textContentHeight - this._hyperlinkData.height) / 2)
|
||||
textContentNested.add(this._hyperlinkData.node)
|
||||
textContentOffsetX += this._hyperlinkData.width + _textContentItemMargin
|
||||
textContentOffsetX += this._hyperlinkData.width + textContentItemMargin
|
||||
}
|
||||
// 标签
|
||||
let tagNested = new G()
|
||||
@ -531,7 +529,7 @@ class Node {
|
||||
this._tagData.forEach((item) => {
|
||||
item.node.x(textContentOffsetX + tagLeft).y((this._rectInfo.textContentHeight - item.height) / 2)
|
||||
tagNested.add(item.node)
|
||||
tagLeft += item.width + _textContentItemMargin
|
||||
tagLeft += item.width + textContentItemMargin
|
||||
})
|
||||
textContentNested.add(tagNested)
|
||||
textContentOffsetX += tagLeft
|
||||
@ -545,7 +543,7 @@ class Node {
|
||||
// 文字内容整体
|
||||
textContentNested.translate(
|
||||
width / 2 - textContentNested.bbox().width / 2,
|
||||
imgHeight + paddingY + (imgHeight > 0 && this._rectInfo.textContentHeight > 0 ? this._blockContentMargin : 0)
|
||||
imgHeight + paddingY + (imgHeight > 0 && this._rectInfo.textContentHeight > 0 ? this.blockContentMargin : 0)
|
||||
)
|
||||
this.group.add(textContentNested)
|
||||
// 单击事件,选中节点
|
||||
@ -606,11 +604,8 @@ class Node {
|
||||
this.removeExpandBtn()
|
||||
} else if (!this._expandBtn && this.nodeData.children.length > 0) {// 需要添加展开收缩按钮
|
||||
this.renderExpandBtn()
|
||||
}
|
||||
if (!layout) {
|
||||
this.updateHooks.forEach((hook) => {
|
||||
hook(this)
|
||||
})
|
||||
} else {
|
||||
this.updateExpandBtnPos()
|
||||
}
|
||||
let t = this.group.transform()
|
||||
if (!layout) {
|
||||
@ -630,8 +625,8 @@ class Node {
|
||||
// 连线
|
||||
this.renderLine()
|
||||
// 节点
|
||||
if (this._initRender) {
|
||||
this._initRender = false
|
||||
if (this.initRender) {
|
||||
this.initRender = false
|
||||
this.renderNode()
|
||||
} else {
|
||||
this.update()
|
||||
@ -652,7 +647,7 @@ class Node {
|
||||
* @Desc: 递归删除
|
||||
*/
|
||||
remove() {
|
||||
this._initRender = true
|
||||
this.initRender = true
|
||||
this.removeAllEvent()
|
||||
this.removeAllNode()
|
||||
this.removeLine()
|
||||
@ -723,10 +718,10 @@ class Node {
|
||||
} else {
|
||||
iconSvg = btnsSvg.close
|
||||
}
|
||||
let node = SVG(iconSvg).size(this._expandBtnSize, this._expandBtnSize)
|
||||
let fillNode = new Circle().size(this._expandBtnSize)
|
||||
node.x(0).y(-this._expandBtnSize / 2)
|
||||
fillNode.x(0).y(-this._expandBtnSize / 2)
|
||||
let node = SVG(iconSvg).size(this.expandBtnSize, this.expandBtnSize)
|
||||
let fillNode = new Circle().size(this.expandBtnSize)
|
||||
node.x(0).y(-this.expandBtnSize / 2)
|
||||
fillNode.x(0).y(-this.expandBtnSize / 2)
|
||||
this.style.iconBtn(node, fillNode)
|
||||
this._expandBtn.add(fillNode).add(node)
|
||||
}
|
||||
@ -741,7 +736,6 @@ class Node {
|
||||
if (!this._expandBtn) {
|
||||
return
|
||||
}
|
||||
console.log('更新')
|
||||
this.renderer.layout.renderExpandBtn(this, this._expandBtn)
|
||||
}
|
||||
|
||||
@ -775,7 +769,7 @@ class Node {
|
||||
this.mindMap.emit('expand_btn_click', this)
|
||||
})
|
||||
this.group.add(this._expandBtn)
|
||||
this.renderer.layout.renderExpandBtn(this, this._expandBtn)
|
||||
this.updateExpandBtnPos()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -44,7 +44,7 @@ class Render {
|
||||
// 根节点
|
||||
this.root = null
|
||||
// 布局
|
||||
this.layout = new (layouts[this.mindMap.opt.layout] ? layouts[this.mindMap.opt.layout] : layouts.logicalStructure)(this)
|
||||
this.setLayout()
|
||||
// 绑定事件
|
||||
this.bindEvent()
|
||||
// 注册命令
|
||||
@ -55,6 +55,16 @@ class Render {
|
||||
this.textEdit = new TextEdit(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-07-13 16:20:07
|
||||
* @Desc: 设置布局结构
|
||||
*/
|
||||
setLayout() {
|
||||
this.layout = new (layouts[this.mindMap.opt.layout] ? layouts[this.mindMap.opt.layout] : layouts.logicalStructure)(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-20 10:34:06
|
||||
@ -371,9 +381,7 @@ class Render {
|
||||
this.setNodeData(node, {
|
||||
isActive: active
|
||||
})
|
||||
let s = Date.now()
|
||||
node.renderNode()
|
||||
console.log(Date.now() - s)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -73,12 +73,27 @@ class Select {
|
||||
* @Desc: 鼠标移动到边缘后移动画布
|
||||
*/
|
||||
move (x, y) {
|
||||
if (x >= this.mindMap.elRect.right - 20) {
|
||||
console.log('小于')
|
||||
let step = this.mindMap.opt.selectTranslateStep
|
||||
let limit = this.mindMap.opt.selectTranslateLimit
|
||||
// 左边缘
|
||||
if (x <= this.mindMap.elRect.left + limit) {
|
||||
this.mouseDownX += step
|
||||
this.mindMap.view.translateX(step)
|
||||
}
|
||||
if (y >= this.mindMap.elRect.bottom - 20) {
|
||||
console.log('小于')
|
||||
this.mindMap.view.translateY(-3)
|
||||
// 右边缘
|
||||
if (x >= this.mindMap.elRect.right - limit) {
|
||||
this.mouseDownX -= step
|
||||
this.mindMap.view.translateX(-step)
|
||||
}
|
||||
// 上边缘
|
||||
if (y <= this.mindMap.elRect.top + limit) {
|
||||
this.mouseDownY += step
|
||||
this.mindMap.view.translateY(step)
|
||||
}
|
||||
// 下边缘
|
||||
if (y >= this.mindMap.elRect.bottom - limit) {
|
||||
this.mouseDownY -= step
|
||||
this.mindMap.view.translateY(-step)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -60,10 +60,23 @@ class View {
|
||||
})
|
||||
}
|
||||
|
||||
translateX() {
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-07-13 15:49:06
|
||||
* @Desc: 平移x方向
|
||||
*/
|
||||
translateX(step) {
|
||||
this.x += step
|
||||
this.transform()
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-07-13 15:48:52
|
||||
* @Desc: 平移y方向
|
||||
*/
|
||||
translateY(step) {
|
||||
this.y += step
|
||||
this.transform()
|
||||
|
||||
BIN
simple-mind-map/src/assets/catalogOrganization.jpg
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
simple-mind-map/src/assets/dark2.jpg
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
simple-mind-map/src/assets/gold.jpg
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
simple-mind-map/src/assets/greenLeaf.jpg
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
BIN
simple-mind-map/src/assets/logicalStructure.jpg
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
simple-mind-map/src/assets/mindMap.jpg
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
simple-mind-map/src/assets/mint.jpg
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
simple-mind-map/src/assets/organizationStructure.jpg
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
simple-mind-map/src/assets/skyGreen.jpg
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
simple-mind-map/src/assets/vitalityOrange.jpg
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
@ -29,9 +29,9 @@ class CatalogOrganization extends Base {
|
||||
let task = [() => {
|
||||
this.computedBaseValue()
|
||||
}, () => {
|
||||
this.computedLeftValue()
|
||||
this.computedLeftTopValue()
|
||||
}, () => {
|
||||
// this.adjustTopValue()
|
||||
this.adjustLeftTopValue()
|
||||
}, () => {
|
||||
callback(this.root)
|
||||
}]
|
||||
@ -53,18 +53,20 @@ class CatalogOrganization extends Base {
|
||||
newNode.top = (this.mindMap.height - newNode.height) / 2
|
||||
} else {
|
||||
// 非根节点
|
||||
// 定位到父节点下方
|
||||
newNode.top = parent._node.top + parent._node.height + this.getMarginX(layerIndex)
|
||||
if (parent._node.isRoot) {
|
||||
newNode.top = parent._node.top + parent._node.height + this.getMarginX(layerIndex)
|
||||
}
|
||||
}
|
||||
if (!cur.data.expand) {
|
||||
return true;
|
||||
}
|
||||
}, (cur, parent, isRoot, layerIndex) => {
|
||||
// 返回时计算节点的areaWidth和areaHeight,也就是子节点所占的高度之和,包括外边距
|
||||
let len = cur.data.expand === false ? 0 : cur._node.children.length
|
||||
cur._node.childrenAreaWidth = len ? cur._node.children.reduce((h, item) => {
|
||||
return h + item.width
|
||||
}, 0) + (len + 1) * this.getMarginY(layerIndex + 1) : 0
|
||||
if (isRoot) {
|
||||
let len = cur.data.expand === false ? 0 : cur._node.children.length
|
||||
cur._node.childrenAreaWidth = len ? cur._node.children.reduce((h, item) => {
|
||||
return h + item.width
|
||||
}, 0) + (len + 1) * this.getMarginX(layerIndex + 1) : 0
|
||||
}
|
||||
}, true, 0)
|
||||
}
|
||||
|
||||
@ -72,19 +74,28 @@ class CatalogOrganization extends Base {
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-08 09:59:25
|
||||
* @Desc: 遍历节点树计算节点的left
|
||||
* @Desc: 遍历节点树计算节点的left、top
|
||||
*/
|
||||
computedLeftValue() {
|
||||
computedLeftTopValue() {
|
||||
walk(this.root, null, (node, parent, isRoot, layerIndex) => {
|
||||
if (node.nodeData.data.expand && node.children && node.children.length) {
|
||||
let marginX = this.getMarginY(layerIndex + 1)
|
||||
// 第一个子节点的left值 = 该节点中心的left值 - 子节点的宽度之和的一半
|
||||
let left = node.left + node.width / 2 - node.childrenAreaWidth / 2
|
||||
let totalLeft = left + marginX
|
||||
node.children.forEach((cur) => {
|
||||
cur.left = totalLeft
|
||||
totalLeft += cur.width + marginX
|
||||
})
|
||||
let marginX = this.getMarginX(layerIndex + 1)
|
||||
let marginY = this.getMarginY(layerIndex + 1)
|
||||
if (isRoot) {
|
||||
let left = node.left + node.width / 2 - node.childrenAreaWidth / 2
|
||||
let totalLeft = left + marginX
|
||||
node.children.forEach((cur) => {
|
||||
cur.left = totalLeft
|
||||
totalLeft += cur.width + marginX
|
||||
})
|
||||
} else {
|
||||
let totalTop = node.top + node.height + marginY + node.expandBtnSize
|
||||
node.children.forEach((cur) => {
|
||||
cur.left = node.left + node.width * 0.5
|
||||
cur.top = totalTop
|
||||
totalTop += cur.height + marginY + node.expandBtnSize
|
||||
})
|
||||
}
|
||||
}
|
||||
}, null, true)
|
||||
}
|
||||
@ -93,17 +104,29 @@ class CatalogOrganization extends Base {
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-08 10:04:05
|
||||
* @Desc: 调整节点top
|
||||
* @Desc: 调整节点left、top
|
||||
*/
|
||||
adjustTopValue() {
|
||||
adjustLeftTopValue() {
|
||||
walk(this.root, null, (node, parent, isRoot, layerIndex) => {
|
||||
if (!node.nodeData.data.expand) {
|
||||
return;
|
||||
}
|
||||
// 判断子节点所占的高度之和是否大于该节点自身,大于则需要调整位置
|
||||
let difference = node.childrenAreaHeight - this.getMarginY(layerIndex + 1) * 2 - node.height
|
||||
if (difference > 0) {
|
||||
this.updateBrothers(node, difference / 2)
|
||||
// 调整left
|
||||
if (parent && parent.isRoot) {
|
||||
let areaWidth = this.getNodeAreaWidth(node)
|
||||
let difference = areaWidth - node.width
|
||||
if (difference > 0) {
|
||||
this.updateBrothersLeft(node, difference / 2)
|
||||
}
|
||||
}
|
||||
// 调整top
|
||||
let len = node.children.length
|
||||
if (parent && !parent.isRoot && len > 0) {
|
||||
let marginY = this.getMarginY(layerIndex + 1)
|
||||
let totalHeight = node.children.reduce((h, item) => {
|
||||
return h + item.height
|
||||
}, 0) + (len + 1) * marginY + len * node.expandBtnSize
|
||||
this.updateBrothersTop(node, totalHeight)
|
||||
}
|
||||
}, null, true)
|
||||
}
|
||||
@ -111,21 +134,80 @@ class CatalogOrganization extends Base {
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 14:26:03
|
||||
* @Desc: 更新兄弟节点的top
|
||||
* @Date: 2021-04-12 18:55:03
|
||||
* @Desc: 递归计算节点的宽度
|
||||
*/
|
||||
updateBrothers(node, addHeight) {
|
||||
getNodeAreaWidth(node) {
|
||||
let widthArr = []
|
||||
let loop = (node, width) => {
|
||||
if (node.children.length) {
|
||||
width += node.width / 2
|
||||
node.children.forEach((item) => {
|
||||
loop(item, width)
|
||||
})
|
||||
} else {
|
||||
width += node.width
|
||||
widthArr.push(width)
|
||||
}
|
||||
}
|
||||
loop(node, 0)
|
||||
return Math.max(...widthArr)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-07-13 11:12:51
|
||||
* @Desc: 调整兄弟节点的left
|
||||
*/
|
||||
updateBrothersLeft(node, addWidth) {
|
||||
if (node.parent) {
|
||||
let childrenList = node.parent.children
|
||||
let index = childrenList.findIndex((item) => {
|
||||
return item === node
|
||||
})
|
||||
// 第一个或最后一个节点自身也需要移动,否则两边不对称
|
||||
if (index === 0 || index === childrenList.length - 1) {
|
||||
let _offset = index === 0 ? -addWidth : addWidth
|
||||
node.left += _offset
|
||||
if (node.children && node.children.length) {
|
||||
this.updateChildren(node.children, 'left', _offset)
|
||||
}
|
||||
}
|
||||
childrenList.forEach((item, _index) => {
|
||||
let _offset = 0
|
||||
if (_index < index) { // 左边的节点往左移
|
||||
_offset = -addWidth
|
||||
} else if (_index > index) { // 右边的节点往右移
|
||||
_offset = addWidth
|
||||
}
|
||||
item.left += _offset
|
||||
// 同步更新子节点的位置
|
||||
if (item.children && item.children.length) {
|
||||
this.updateChildren(item.children, 'left', _offset)
|
||||
}
|
||||
})
|
||||
// 更新父节点的位置
|
||||
this.updateBrothersLeft(node.parent, addWidth)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 14:26:03
|
||||
* @Desc: 调整兄弟节点的top
|
||||
*/
|
||||
updateBrothersTop(node, addHeight) {
|
||||
if (node.parent && !node.parent.isRoot) {
|
||||
let childrenList = node.parent.children
|
||||
let index = childrenList.findIndex((item) => {
|
||||
return item === node
|
||||
})
|
||||
childrenList.forEach((item, _index) => {
|
||||
let _offset = 0
|
||||
// 上面的节点往上移
|
||||
if (_index < index) {
|
||||
_offset = -addHeight
|
||||
} else if (_index > index) { // 下面的节点往下移
|
||||
// 下面的节点往下移
|
||||
if (_index > index) {
|
||||
_offset = addHeight
|
||||
}
|
||||
item.top += _offset
|
||||
@ -135,7 +217,7 @@ class CatalogOrganization extends Base {
|
||||
}
|
||||
})
|
||||
// 更新父节点的位置
|
||||
this.updateBrothers(node.parent, addHeight)
|
||||
this.updateBrothersTop(node.parent, addHeight)
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,7 +227,6 @@ class CatalogOrganization extends Base {
|
||||
* @Desc: 绘制连线,连接该节点到其子节点
|
||||
*/
|
||||
renderLine(node, lines) {
|
||||
return
|
||||
if (node.children.length <= 0) {
|
||||
return [];
|
||||
}
|
||||
@ -153,21 +234,61 @@ class CatalogOrganization extends Base {
|
||||
left,
|
||||
top,
|
||||
width,
|
||||
height
|
||||
height,
|
||||
expandBtnSize
|
||||
} = node
|
||||
node.children.forEach((item, index) => {
|
||||
let x1 = node.layerIndex === 0 ? left + width / 2 : left + width + 20
|
||||
let y1 = node.layerIndex === 0 ? top + height / 2 : top + height / 2
|
||||
let x2 = item.left
|
||||
let y2 = item.top + item.height / 2
|
||||
let path = ''
|
||||
if (node.isRoot) {
|
||||
path = this.quadraticCurvePath(x1, y1, x2, y2)
|
||||
} else {
|
||||
path = this.cubicBezierPath(x1, y1, x2, y2)
|
||||
let len = node.children.length
|
||||
let marginX = this.getMarginX(node.layerIndex + 1)
|
||||
if (node.isRoot) {
|
||||
let x1 = left + width / 2
|
||||
let y1 = top + height
|
||||
let s1 = marginX * 0.7
|
||||
let minx = 0
|
||||
let maxx = 0
|
||||
node.children.forEach((item, index) => {
|
||||
let x2 = item.left +item.width / 2
|
||||
let y2 = item.top
|
||||
if (index === 0) {
|
||||
minx = x2
|
||||
} else if (index >= len - 1) {
|
||||
maxx = x2
|
||||
}
|
||||
let path = `M ${x2},${y1 + s1} L ${x2},${y2}`
|
||||
lines[index].plot(path)
|
||||
})
|
||||
// 父节点的竖线
|
||||
let line1 = this.draw.path()
|
||||
node.style.line(line1)
|
||||
line1.plot(`M ${x1},${y1} L ${x1},${y1 + s1}`)
|
||||
node._lines.push(line1)
|
||||
// 水平线
|
||||
if (len > 1) {
|
||||
let lin2 = this.draw.path()
|
||||
node.style.line(lin2)
|
||||
lin2.plot(`M ${minx},${y1 + s1} L ${maxx},${y1 + s1}`)
|
||||
node._lines.push(lin2)
|
||||
}
|
||||
lines[index].plot(path)
|
||||
})
|
||||
} else {
|
||||
let y1 = top + height
|
||||
let maxy = 0
|
||||
let x2 = node.left + node.width * 0.3
|
||||
node.children.forEach((item, index) => {
|
||||
let y2 = item.top + item.height / 2
|
||||
if (index >= len - 1) {
|
||||
maxy = y2
|
||||
}
|
||||
let path = `M ${x2},${y2} L ${x2 + node.width * 0.2},${y2}`
|
||||
lines[index].plot(path)
|
||||
})
|
||||
// 竖线
|
||||
if (len > 0) {
|
||||
let lin2 = this.draw.path()
|
||||
expandBtnSize = len > 0 ? expandBtnSize : 0
|
||||
node.style.line(lin2)
|
||||
lin2.plot(`M ${x2},${y1 + expandBtnSize} L ${x2},${maxy}`)
|
||||
node._lines.push(lin2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -176,12 +297,19 @@ class CatalogOrganization extends Base {
|
||||
* @Desc: 渲染按钮
|
||||
*/
|
||||
renderExpandBtn(node, btn) {
|
||||
return
|
||||
let {
|
||||
width,
|
||||
height
|
||||
height,
|
||||
expandBtnSize,
|
||||
isRoot
|
||||
} = node
|
||||
btn.translate(width, height / 2)
|
||||
if (!isRoot) {
|
||||
let {
|
||||
translateX,
|
||||
translateY
|
||||
} = btn.transform()
|
||||
btn.translate(width * 0.3 - expandBtnSize / 2 - translateX, height + expandBtnSize / 2 - translateY)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -179,7 +179,11 @@ class LogicalStructure extends Base {
|
||||
width,
|
||||
height
|
||||
} = node
|
||||
btn.translate(width, height / 2)
|
||||
let {
|
||||
translateX,
|
||||
translateY
|
||||
} = btn.transform()
|
||||
btn.translate(width - translateX, height / 2 - translateY)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -48,12 +48,6 @@ class MindMap extends Base {
|
||||
computedBaseValue() {
|
||||
walk(this.renderer.renderTree, null, (cur, parent, isRoot, layerIndex, index) => {
|
||||
let newNode = this.createNode(cur, parent, isRoot, layerIndex)
|
||||
// 更新时展开收缩按钮位置可能会变化,需要更新
|
||||
if (newNode.updateHooks.length <= 0) {
|
||||
newNode.updateHooks.push((node) => {
|
||||
node.updateExpandBtnPos()
|
||||
})
|
||||
}
|
||||
// 根节点定位在画布中心位置
|
||||
if (isRoot) {
|
||||
newNode.left = (this.mindMap.width - newNode.width) / 2
|
||||
@ -195,10 +189,10 @@ class MindMap extends Base {
|
||||
top,
|
||||
width,
|
||||
height,
|
||||
_expandBtnSize
|
||||
expandBtnSize
|
||||
} = node
|
||||
node.children.forEach((item, index) => {
|
||||
let x1 = node.layerIndex === 0 ? left + width / 2 : item.dir === 'left' ? left - _expandBtnSize : left + width + 20
|
||||
let x1 = node.layerIndex === 0 ? left + width / 2 : item.dir === 'left' ? left - expandBtnSize : left + width + 20
|
||||
let y1 = node.layerIndex === 0 ? top + height / 2 : top + height / 2
|
||||
let x2 = item.dir === 'left' ? item.left + item.width : item.left
|
||||
let y2 = item.top + item.height / 2
|
||||
@ -221,13 +215,13 @@ class MindMap extends Base {
|
||||
let {
|
||||
width,
|
||||
height,
|
||||
_expandBtnSize
|
||||
expandBtnSize
|
||||
} = node
|
||||
let {
|
||||
translateX,
|
||||
translateY
|
||||
} = btn.transform()
|
||||
let x = (node.dir === 'left' ? 0 - _expandBtnSize : width) - translateX
|
||||
let x = (node.dir === 'left' ? 0 - expandBtnSize : width) - translateX
|
||||
let y = height / 2 - translateY
|
||||
btn.translate(x, y)
|
||||
}
|
||||
|
||||
@ -154,7 +154,7 @@ class OrganizationStructure extends Base {
|
||||
top,
|
||||
width,
|
||||
height,
|
||||
_expandBtnSize,
|
||||
expandBtnSize,
|
||||
isRoot
|
||||
} = node
|
||||
let x1 = left + width / 2
|
||||
@ -178,8 +178,8 @@ class OrganizationStructure extends Base {
|
||||
// 父节点的竖线
|
||||
let line1 = this.draw.path()
|
||||
node.style.line(line1)
|
||||
_expandBtnSize = len > 0 && !isRoot ? _expandBtnSize : 0
|
||||
line1.plot(`M ${x1},${y1 + _expandBtnSize} L ${x1},${y1 + s1}`)
|
||||
expandBtnSize = len > 0 && !isRoot ? expandBtnSize : 0
|
||||
line1.plot(`M ${x1},${y1 + expandBtnSize} L ${x1},${y1 + s1}`)
|
||||
node._lines.push(line1)
|
||||
// 水平线
|
||||
if (len > 1) {
|
||||
@ -199,9 +199,13 @@ class OrganizationStructure extends Base {
|
||||
let {
|
||||
width,
|
||||
height,
|
||||
_expandBtnSize
|
||||
expandBtnSize
|
||||
} = node
|
||||
btn.translate(width / 2 - _expandBtnSize / 2, height + _expandBtnSize / 2)
|
||||
let {
|
||||
translateX,
|
||||
translateY
|
||||
} = btn.transform()
|
||||
btn.translate(width / 2 - expandBtnSize / 2 - translateX, height + expandBtnSize / 2 - translateY)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,270 +0,0 @@
|
||||
import {
|
||||
walk
|
||||
} from '../Utils'
|
||||
import Node from '../Node'
|
||||
import merge from 'deepmerge'
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-08 16:25:07
|
||||
* @Desc: 目录组织图
|
||||
* 思路:第一轮只计算节点的宽高,以及某个节点的所有子节点所占的高度之和,以及该节点里所有子节点中宽度最宽是多少、第二轮计算节点的left和top,需要区分二级节点和其他节点,二级节点top相同,一行依次从做向右排开,其他节点的left相同,一列从上往下依次排开
|
||||
*/
|
||||
class Render {
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-08 16:25:32
|
||||
* @Desc: 构造函数
|
||||
*/
|
||||
constructor(opt = {}) {
|
||||
this.opt = opt
|
||||
this.mindMap = opt.mindMap
|
||||
this.draw = this.mindMap.draw
|
||||
// 渲染树
|
||||
this.renderTree = merge({}, this.mindMap.opt.data || {})
|
||||
// 根节点
|
||||
this.root = null
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-08 16:27:55
|
||||
* @Desc: 渲染
|
||||
*/
|
||||
render() {
|
||||
this.computed()
|
||||
this.root.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-06 14:04:20
|
||||
* @Desc: 计算位置数据
|
||||
*/
|
||||
computed() {
|
||||
// 计算节点的width、height
|
||||
this.computedBaseValue()
|
||||
// 计算节点的left、top
|
||||
this.computedLeftTopValue()
|
||||
// 调整节点top
|
||||
this.adjustTopValue()
|
||||
// 调整节点left
|
||||
this.adjustLeftValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-08 09:49:32
|
||||
* @Desc: 计算节点的width、height
|
||||
*/
|
||||
computedBaseValue() {
|
||||
walk(this.renderTree, null, (node, parent, isRoot) => {
|
||||
// 设置width、height
|
||||
let {
|
||||
children,
|
||||
...props
|
||||
} = node
|
||||
let newNode = new Node({
|
||||
...props,
|
||||
mindMap: this.mindMap,
|
||||
draw: this.draw
|
||||
})
|
||||
// 计算节点的宽高
|
||||
newNode.getSize()
|
||||
// 计算节点的top
|
||||
if (isRoot) {
|
||||
newNode.isRoot = true
|
||||
newNode.left = (this.mindMap.width - newNode.width) / 2
|
||||
newNode.top = (this.mindMap.height - newNode.height) / 2
|
||||
this.root = newNode
|
||||
} else {
|
||||
newNode.parent = parent._node
|
||||
parent._node.addChildren(newNode)
|
||||
}
|
||||
node._node = newNode
|
||||
}, (node) => {
|
||||
// 遍历完子节点返回时
|
||||
// 计算节点的areaHeight,也就是子节点所占的高度之和,包括外边距
|
||||
let len = node._node.children.length
|
||||
if (node._node.isRoot) {
|
||||
node._node.childrenAreaWidth = len ? node._node.children.reduce((h, cur) => {
|
||||
return h + cur.width
|
||||
}, 0) + (len + 1) * this.mindMap.opt.marginX : 0
|
||||
}
|
||||
node._node.childrenAreaHeight = len ? node._node.children.reduce((h, cur) => {
|
||||
return h + cur.height
|
||||
}, 0) + (len + 1) * this.mindMap.opt.marginY : 0
|
||||
}, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-08 09:59:25
|
||||
* @Desc: 计算节点的left、top
|
||||
*/
|
||||
computedLeftTopValue() {
|
||||
walk(this.root, null, (node) => {
|
||||
if (node.children && node.children.length) {
|
||||
if (node.isRoot) {
|
||||
let left = node.left + node.width / 2 - node.childrenAreaWidth / 2
|
||||
let totalLeft = left + this.mindMap.opt.marginX
|
||||
node.children.forEach((cur) => {
|
||||
// left
|
||||
cur.left = totalLeft
|
||||
totalLeft += cur.width + this.mindMap.opt.marginX
|
||||
// top
|
||||
cur.top = node.top + node.height + this.mindMap.opt.marginY
|
||||
})
|
||||
} else {
|
||||
let totalTop = node.top + node.height + this.mindMap.opt.marginY
|
||||
node.children.forEach((cur) => {
|
||||
cur.left = node.left + node.width / 5 + this.mindMap.opt.marginX
|
||||
cur.top = totalTop
|
||||
totalTop += cur.height + this.mindMap.opt.marginY
|
||||
})
|
||||
}
|
||||
}
|
||||
}, null, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-12 17:07:29
|
||||
* @Desc: 调整节点left
|
||||
*/
|
||||
adjustLeftValue() {
|
||||
walk(this.root, null, (node) => {
|
||||
if (node.parent && node.parent.isRoot) {
|
||||
let childrenAreaWidth = this.getNodeWidth(node)
|
||||
let difference = childrenAreaWidth - node.width
|
||||
if (difference > 0) {
|
||||
this.updateBrothersLeftValue(node, difference / 2)
|
||||
}
|
||||
}
|
||||
}, null, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-12 18:55:03
|
||||
* @Desc: 计算节点的宽度,包括子节点
|
||||
*/
|
||||
getNodeWidth(node) {
|
||||
let widthArr = []
|
||||
let loop = (node, width) => {
|
||||
if (node.children.length) {
|
||||
width += node.width / 5 + this.mindMap.opt.marginX
|
||||
node.children.forEach((item) => {
|
||||
loop(item, width)
|
||||
})
|
||||
} else {
|
||||
width += node.width
|
||||
widthArr.push(width)
|
||||
}
|
||||
}
|
||||
loop(node, 0)
|
||||
return Math.max(...widthArr)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-12 18:21:46
|
||||
* @Desc: 调整兄弟节点的left
|
||||
*/
|
||||
updateBrothersLeftValue(node, addWidth) {
|
||||
if (node.parent) {
|
||||
let childrenList = node.parent.children
|
||||
let index = childrenList.findIndex((item) => {
|
||||
return item === node
|
||||
})
|
||||
childrenList.forEach((item, _index) => {
|
||||
let _offset = 0
|
||||
if (_index > index) {
|
||||
_offset = addWidth
|
||||
} else {
|
||||
_offset = -addWidth
|
||||
}
|
||||
item.left += _offset
|
||||
// 同步更新子节点的位置
|
||||
if (item.children && item.children.length) {
|
||||
this.updateChildren(item.children, 'left', _offset)
|
||||
}
|
||||
})
|
||||
// 更新父节点的位置
|
||||
this.updateBrothersLeftValue(node.parent, addWidth)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-08 10:04:05
|
||||
* @Desc: 调整节点top,该节点之后的节点都往下进行偏移
|
||||
*/
|
||||
adjustTopValue() {
|
||||
let marginY = this.mindMap.opt.marginY
|
||||
walk(this.root, null, (node) => {
|
||||
if (!node.isRoot && !node.parent.isRoot) {
|
||||
// 判断子节点的areaHeight是否大于该节点自身,大于则需要调整位置
|
||||
if (node.children && node.children.length > 0) {
|
||||
let difference = node.childrenAreaHeight - marginY
|
||||
this.updateBrothersTopValue(node, difference)
|
||||
}
|
||||
}
|
||||
}, null, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 14:26:03
|
||||
* @Desc: 更新兄弟节点的top
|
||||
*/
|
||||
updateBrothersTopValue(node, addHeight) {
|
||||
if (node.parent && !node.parent.isRoot) {
|
||||
let childrenList = node.parent.children
|
||||
let index = childrenList.findIndex((item) => {
|
||||
return item === node
|
||||
})
|
||||
childrenList.forEach((item, _index) => {
|
||||
let _offset = 0
|
||||
if (_index > index) {
|
||||
_offset = addHeight
|
||||
}
|
||||
item.top += _offset
|
||||
// 同步更新子节点的位置
|
||||
if (item.children && item.children.length) {
|
||||
this.updateChildren(item.children, 'top', _offset)
|
||||
}
|
||||
})
|
||||
// 更新父节点的位置
|
||||
this.updateBrothersTopValue(node.parent, addHeight)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-04-07 11:25:52
|
||||
* @Desc: 更新子节点属性
|
||||
*/
|
||||
updateChildren(children, prop, offset) {
|
||||
children.forEach((item) => {
|
||||
item[prop] += offset
|
||||
if (item.children && item.children.length) {
|
||||
this.updateChildren(item.children, prop, offset)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default Render
|
||||
@ -26,6 +26,36 @@ export const tagColorList = [
|
||||
}
|
||||
]
|
||||
|
||||
/**
|
||||
* javascript comment
|
||||
* @Author: 王林25
|
||||
* @Date: 2021-07-13 15:56:28
|
||||
* @Desc: 布局结构列表
|
||||
*/
|
||||
export const layoutList = [
|
||||
{
|
||||
name: '逻辑结构图',
|
||||
value: 'logicalStructure',
|
||||
img: require('../assets/logicalStructure.jpg')
|
||||
},
|
||||
{
|
||||
name: '思维导图',
|
||||
value: 'mindMap',
|
||||
img: require('../assets/mindMap.jpg')
|
||||
},
|
||||
{
|
||||
name: '组织结构图',
|
||||
value: 'organizationStructure',
|
||||
img: require('../assets/organizationStructure.jpg')
|
||||
},
|
||||
{
|
||||
name: '目录组织图',
|
||||
value: 'catalogOrganization',
|
||||
img: require('../assets/catalogOrganization.jpg')
|
||||
}
|
||||
]
|
||||
export const layoutValueList = ['logicalStructure', 'mindMap', 'catalogOrganization', 'organizationStructure']
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 22:58:42
|
||||
@ -52,6 +82,36 @@ export const themeList = [
|
||||
value: 'pinkGrape',
|
||||
img: require('../assets/pinkGrape.jpg')
|
||||
},
|
||||
{
|
||||
name: '薄荷',
|
||||
value: 'mint',
|
||||
img: require('../assets/mint.jpg')
|
||||
},
|
||||
{
|
||||
name: '金色vip',
|
||||
value: 'gold',
|
||||
img: require('../assets/gold.jpg')
|
||||
},
|
||||
{
|
||||
name: '活力橙',
|
||||
value: 'vitalityOrange',
|
||||
img: require('../assets/vitalityOrange.jpg')
|
||||
},
|
||||
{
|
||||
name: '绿叶',
|
||||
value: 'greenLeaf',
|
||||
img: require('../assets/greenLeaf.jpg')
|
||||
},
|
||||
{
|
||||
name: '暗色2',
|
||||
value: 'dark2',
|
||||
img: require('../assets/dark2.jpg')
|
||||
},
|
||||
{
|
||||
name: '天清绿',
|
||||
value: 'skyGreen',
|
||||
img: require('../assets/skyGreen.jpg')
|
||||
},
|
||||
{
|
||||
name: '脑图经典2',
|
||||
value: 'classic2',
|
||||
|
||||
@ -1,9 +1,25 @@
|
||||
<template>
|
||||
<Sidebar ref="sidebar" title="结构"> </Sidebar>
|
||||
<Sidebar ref="sidebar" title="结构">
|
||||
<div class="layoutList">
|
||||
<div
|
||||
class="layoutItem"
|
||||
v-for="item in layoutList"
|
||||
:key="item.value"
|
||||
@click="useLayout(item)"
|
||||
:class="{ active: item.value === layout }"
|
||||
>
|
||||
<div class="imgBox">
|
||||
<img :src="item.img" alt="" />
|
||||
</div>
|
||||
<div class="name">{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Sidebar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Sidebar from "./Sidebar";
|
||||
import { layoutList } from "simple-mind-map/src/utils/constant";
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
@ -15,19 +31,77 @@ export default {
|
||||
components: {
|
||||
Sidebar,
|
||||
},
|
||||
props: {
|
||||
mindMap: {
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
return {
|
||||
layoutList,
|
||||
layout: ''
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$bus.$on("showStructure", () => {
|
||||
this.$refs.sidebar.show = false;
|
||||
this.$nextTick(() => {
|
||||
this.layout = this.mindMap.getLayout();
|
||||
this.$refs.sidebar.show = true;
|
||||
});
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 23:04:38
|
||||
* @Desc: 使用主题
|
||||
*/
|
||||
useLayout(layout) {
|
||||
this.layout = layout.value;
|
||||
this.mindMap.setLayout(layout.value);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.layoutList {
|
||||
padding: 20px;
|
||||
|
||||
.layoutItem {
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
border-bottom: 1px solid #e9e9e9;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 20px;
|
||||
transition: all 0.2s;
|
||||
border: 1px solid transparent;
|
||||
|
||||
&:last-of-type {
|
||||
border: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 1px 2px -2px rgba(0, 0, 0, 0.16),
|
||||
0 3px 6px 0 rgba(0, 0, 0, 0.12), 0 5px 12px 4px rgba(0, 0, 0, 0.09);
|
||||
}
|
||||
|
||||
&.active {
|
||||
border: 1px solid #67c23a;
|
||||
}
|
||||
|
||||
.imgBox {
|
||||
width: 100%;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.name {
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||