Demo:支持点击节点标签进行文本和颜色的修改
This commit is contained in:
parent
12c6479c0d
commit
4777ab3e58
@ -97,7 +97,7 @@ export const colorList = [
|
|||||||
'#0C797D',
|
'#0C797D',
|
||||||
'#0062B1',
|
'#0062B1',
|
||||||
'#653294',
|
'#653294',
|
||||||
'#AB149E',
|
// '#AB149E',
|
||||||
'transparent'
|
'transparent'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -373,5 +373,9 @@ export default {
|
|||||||
boxStyle: 'Box style',
|
boxStyle: 'Box style',
|
||||||
boxColor: 'Box color',
|
boxColor: 'Box color',
|
||||||
fillColor: 'Fill color'
|
fillColor: 'Fill color'
|
||||||
|
},
|
||||||
|
nodeTagStyle: {
|
||||||
|
placeholder: 'Please enter the tag content',
|
||||||
|
delete: 'Delete this tag'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -365,5 +365,9 @@ export default {
|
|||||||
boxStyle: '边框样式',
|
boxStyle: '边框样式',
|
||||||
boxColor: '边框颜色',
|
boxColor: '边框颜色',
|
||||||
fillColor: '填充颜色'
|
fillColor: '填充颜色'
|
||||||
|
},
|
||||||
|
nodeTagStyle: {
|
||||||
|
placeholder: '请输入标签内容',
|
||||||
|
delete: '删除此标签'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,6 +37,7 @@
|
|||||||
<FormulaSidebar v-if="mindMap" :mindMap="mindMap"></FormulaSidebar>
|
<FormulaSidebar v-if="mindMap" :mindMap="mindMap"></FormulaSidebar>
|
||||||
<SourceCodeEdit v-if="mindMap" :mindMap="mindMap"></SourceCodeEdit>
|
<SourceCodeEdit v-if="mindMap" :mindMap="mindMap"></SourceCodeEdit>
|
||||||
<NodeOuterFrame v-if="mindMap" :mindMap="mindMap"></NodeOuterFrame>
|
<NodeOuterFrame v-if="mindMap" :mindMap="mindMap"></NodeOuterFrame>
|
||||||
|
<NodeTagStyle v-if="mindMap" :mindMap="mindMap"></NodeTagStyle>
|
||||||
<div
|
<div
|
||||||
class="dragMask"
|
class="dragMask"
|
||||||
v-if="showDragMask"
|
v-if="showDragMask"
|
||||||
@ -112,6 +113,7 @@ import FormulaSidebar from './FormulaSidebar.vue'
|
|||||||
import SourceCodeEdit from './SourceCodeEdit.vue'
|
import SourceCodeEdit from './SourceCodeEdit.vue'
|
||||||
import NodeAttachment from './NodeAttachment.vue'
|
import NodeAttachment from './NodeAttachment.vue'
|
||||||
import NodeOuterFrame from './NodeOuterFrame.vue'
|
import NodeOuterFrame from './NodeOuterFrame.vue'
|
||||||
|
import NodeTagStyle from './NodeTagStyle.vue'
|
||||||
|
|
||||||
// 注册插件
|
// 注册插件
|
||||||
MindMap.usePlugin(MiniMap)
|
MindMap.usePlugin(MiniMap)
|
||||||
@ -168,7 +170,8 @@ export default {
|
|||||||
FormulaSidebar,
|
FormulaSidebar,
|
||||||
SourceCodeEdit,
|
SourceCodeEdit,
|
||||||
NodeAttachment,
|
NodeAttachment,
|
||||||
NodeOuterFrame
|
NodeOuterFrame,
|
||||||
|
NodeTagStyle
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|||||||
247
web/src/pages/Edit/components/NodeTagStyle.vue
Normal file
247
web/src/pages/Edit/components/NodeTagStyle.vue
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="nodeTagStyleContainer"
|
||||||
|
ref="elRef"
|
||||||
|
:style="position"
|
||||||
|
v-show="show"
|
||||||
|
:class="{ isDark: isDark }"
|
||||||
|
>
|
||||||
|
<div class="row">
|
||||||
|
<el-input
|
||||||
|
v-model="text"
|
||||||
|
:placeholder="$t('nodeTagStyle.placeholder')"
|
||||||
|
size="mini"
|
||||||
|
@blur="updateTagText"
|
||||||
|
@keydown.native.stop
|
||||||
|
@keyup.native.enter.stop="updateTagText"
|
||||||
|
></el-input>
|
||||||
|
<div class="deleteBtn" @click.stop="deleteTag">
|
||||||
|
<span class="iconfont iconshanchu"></span>
|
||||||
|
<span class="text">{{ $t('nodeTagStyle.delete') }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<Color :color="fill" @change="updateTagFill"></Color>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Color from './Color'
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Color
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
mindMap: {
|
||||||
|
type: Object
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
show: false,
|
||||||
|
position: {
|
||||||
|
left: 0,
|
||||||
|
top: 0
|
||||||
|
},
|
||||||
|
node: null,
|
||||||
|
index: 0,
|
||||||
|
text: '',
|
||||||
|
fill: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
isDark: state => state.localConfig.isDark
|
||||||
|
})
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.mindMap.on('node_tag_click', this.onNodeTagClick)
|
||||||
|
this.mindMap.on('scale', this.hide)
|
||||||
|
this.mindMap.on('translate', this.hide)
|
||||||
|
this.mindMap.on('svg_mousedown', this.hide)
|
||||||
|
this.mindMap.on('expand_btn_click', this.hide)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.mindMap.off('node_tag_click', this.onNodeTagClick)
|
||||||
|
this.mindMap.off('scale', this.hide)
|
||||||
|
this.mindMap.off('translate', this.hide)
|
||||||
|
this.mindMap.off('svg_mousedown', this.hide)
|
||||||
|
this.mindMap.off('expand_btn_click', this.hide)
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
document.body.appendChild(this.$refs.elRef)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onNodeTagClick(node, tag, index, el) {
|
||||||
|
this.node = node
|
||||||
|
this.index = index
|
||||||
|
if (typeof tag === 'string') {
|
||||||
|
this.text = tag
|
||||||
|
} else {
|
||||||
|
// v0.10.3+版本支持对象类型
|
||||||
|
this.text = tag.text
|
||||||
|
this.fill = tag.style && tag.style.fill ? tag.style.fill : ''
|
||||||
|
}
|
||||||
|
// 获取外框的位置大小信息
|
||||||
|
const { x, y, width, height } = el.rbox()
|
||||||
|
const boxWidth = 260
|
||||||
|
const boxHeight = 152
|
||||||
|
let left = x + width / 2 - boxWidth / 2
|
||||||
|
if (left < 0) {
|
||||||
|
left = 0
|
||||||
|
}
|
||||||
|
if (left + boxWidth > window.innerWidth) {
|
||||||
|
left = window.innerWidth - boxWidth
|
||||||
|
}
|
||||||
|
this.position.left = left + 'px'
|
||||||
|
let top = y + height + 5
|
||||||
|
if (top + boxHeight > window.innerHeight) {
|
||||||
|
top = window.innerHeight - boxHeight
|
||||||
|
}
|
||||||
|
this.position.top = top + 'px'
|
||||||
|
this.show = true
|
||||||
|
},
|
||||||
|
|
||||||
|
updateTagText() {
|
||||||
|
const text = this.text.trim()
|
||||||
|
if (!text) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.updateTagInfo({
|
||||||
|
text
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
updateTagFill(color) {
|
||||||
|
this.updateTagInfo({
|
||||||
|
style: {
|
||||||
|
fill: color
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.fill = color
|
||||||
|
},
|
||||||
|
|
||||||
|
updateTagInfo({ text, style }) {
|
||||||
|
if (!this.node) return
|
||||||
|
const tagData = [...this.node.getData('tag')]
|
||||||
|
let item = null
|
||||||
|
if (typeof tagData[this.index] === 'string') {
|
||||||
|
item = {
|
||||||
|
text: tagData[this.index],
|
||||||
|
style: {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item = tagData[this.index]
|
||||||
|
if (!item.style) {
|
||||||
|
item.style = {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (text) {
|
||||||
|
item.text = text
|
||||||
|
}
|
||||||
|
if (style) {
|
||||||
|
Object.keys(style).forEach(key => {
|
||||||
|
item.style[key] = style[key]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
tagData[this.index] = item
|
||||||
|
this.mindMap.execCommand('SET_NODE_TAG', this.node, tagData)
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteTag() {
|
||||||
|
if (!this.node) return
|
||||||
|
const tagData = [...this.node.getData('tag')]
|
||||||
|
tagData.splice(this.index, 1)
|
||||||
|
this.mindMap.execCommand('SET_NODE_TAG', this.node, tagData)
|
||||||
|
this.hide()
|
||||||
|
},
|
||||||
|
|
||||||
|
hide() {
|
||||||
|
this.show = false
|
||||||
|
this.node = null
|
||||||
|
this.index = 0
|
||||||
|
this.text = ''
|
||||||
|
this.fill = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.nodeTagStyleContainer {
|
||||||
|
position: fixed;
|
||||||
|
width: 260px;
|
||||||
|
padding: 12px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0 2px 16px 0 rgba(0, 0, 0, 0.06);
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
|
&.isDark {
|
||||||
|
background-color: #262a2e;
|
||||||
|
border-left-color: hsla(0, 0%, 100%, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
&:last-of-type {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colorItem {
|
||||||
|
display: inline-block;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colorItemBox {
|
||||||
|
height: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.colorTriggerBtn {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.colorItem {
|
||||||
|
height: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.deleteBtn {
|
||||||
|
white-space: nowrap;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #9aa5b8;
|
||||||
|
font-size: 12px;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #eb5555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 12px;
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
x
Reference in New Issue
Block a user