Demo:支持点击节点内的图标显示一个图标快捷替换和删除悬浮面板

This commit is contained in:
wanglin2 2023-07-29 16:08:12 +08:00
parent 20eba7b29b
commit 78f5d4ec88
5 changed files with 220 additions and 5 deletions

View File

@ -65,7 +65,7 @@ function createIconNode() {
}
node.size(iconSize, iconSize)
node.on('click', e => {
this.mindMap.emit('node_icon_click', this, e)
this.mindMap.emit('node_icon_click', this, item, e)
})
return {
node,

View File

@ -19,7 +19,8 @@
<NodeImgPreview v-if="mindMap" :mindMap="mindMap"></NodeImgPreview>
<SidebarTrigger v-if="!isZenMode"></SidebarTrigger>
<Search v-if="mindMap" :mindMap="mindMap"></Search>
<NodeIconSidebar></NodeIconSidebar>
<NodeIconSidebar v-if="mindMap" :mindMap="mindMap"></NodeIconSidebar>
<NodeIconToolbar v-if="mindMap" :mindMap="mindMap"></NodeIconToolbar>
</div>
</template>
@ -64,6 +65,7 @@ import store from '../../../store'
import i18n from '../../../i18n'
import Search from './Search.vue'
import NodeIconSidebar from './NodeIconSidebar.vue'
import NodeIconToolbar from './NodeIconToolbar.vue'
//
MindMap
@ -108,7 +110,8 @@ export default {
NodeImgPreview,
SidebarTrigger,
Search,
NodeIconSidebar
NodeIconSidebar,
NodeIconToolbar
},
data() {
return {

View File

@ -37,14 +37,13 @@
<script>
import Sidebar from './Sidebar'
import { shortcutKeyList } from '@/config'
import { mapState } from 'vuex'
import { nodeIconList } from 'simple-mind-map/src/svg/icons'
import icon from '@/config/icon'
import image from '@/config/image'
export default {
name: 'ShortcutKey',
name: 'NodeIconSidebar',
components: {
Sidebar
},

View File

@ -0,0 +1,212 @@
<template>
<div class="nodeIconToolbar" ref="nodeIconToolbar" :style="style" @click.stop.passive v-show="showNodeIconToolbar">
<div class="iconListBox">
<div class="icon" v-for="icon in iconList" :key="icon.name" v-html="getHtml(icon.icon)" :class="{
selected: nodeIconList.includes(iconType + '_' + icon.name)
}" @click="setIcon(icon.name)"></div>
</div>
<div class="btnBox">
<span class="btn iconfont iconshanchu" @click="deleteIcon"></span>
</div>
</div>
</template>
<script>
import { nodeIconList as _nodeIconList } from 'simple-mind-map/src/svg/icons'
import icon from '@/config/icon'
import { mapState, mapMutations } from 'vuex'
const allIconList = [..._nodeIconList, ...icon]
export default {
name: 'NodeIconToolbar',
components: {
},
props: {
mindMap: {
type: Object
}
},
data() {
return {
showNodeIconToolbar: false,
style: {
left: 0,
top: 0
},
node: null,
iconType: '',
iconName: '',
nodeIconList: [],
iconList: []
}
},
computed: {
...mapState(['activeSidebar']),
},
created() {
this.mindMap.on('node_icon_click', this.show)
this.mindMap.on('draw_click', this.close)
this.mindMap.on('svg_mousedown', this.close)
this.mindMap.on('node_dblclick', this.close)
this.mindMap.on('node_active', this.onNodeActive)
this.$bus.$on('close_node_icon_toolbar', this.close)
},
mounted() {
document.body.append(this.$refs.nodeIconToolbar)
},
beforeDestroy() {
this.mindMap.off('node_icon_click', this.show)
this.mindMap.off('draw_click', this.close)
this.mindMap.off('svg_mousedown', this.close)
this.mindMap.off('node_dblclick', this.close)
this.mindMap.off('node_active', this.onNodeActive)
this.$bus.$off('close_node_icon_toolbar', this.close)
},
methods: {
...mapMutations(['setActiveSidebar']),
show(node, icon) {
this.node = node
this.iconType = icon.split('_')[0]
this.iconName = icon.split('_')[1]
this.nodeIconList = node.getData('icon') || []
this.iconList = [...allIconList.find((item) => {
return item.type === this.iconType
}).list]
let rect = node.group.rbox()
this.style.left = rect.x + 'px'
this.style.top = rect.y + rect.height + 'px'
this.showNodeIconToolbar = true
if (this.activeSidebar === 'nodeIconSidebar') {
this.setActiveSidebar('')
}
},
close() {
this.showNodeIconToolbar = false
this.node = null
this.iconType = ''
this.iconName = ''
this.nodeIconList = []
this.iconList = []
this.style.left = 0
this.style.top = 0
},
onNodeActive(node) {
if (node === this.node) {
return
}
this.close()
},
deleteIcon() {
this.setIcon(this.iconName)
this.close()
},
//
getHtml(icon) {
return /^<svg/.test(icon) ? icon : `<img src="${icon}" />`
},
// icon
setIcon(name) {
let key = this.iconType + '_' + name
let index = this.nodeIconList.findIndex(item => {
return item === key
})
// icon
if (index !== -1) {
this.nodeIconList.splice(index, 1)
} else {
let typeIndex = this.nodeIconList.findIndex(item => {
return item.split('_')[0] === this.iconType
})
// icon
if (typeIndex !== -1) {
this.nodeIconList.splice(typeIndex, 1, key)
this.iconName = name
} else {
// icon
this.nodeIconList.push(key)
}
}
this.node.setIcon([...this.nodeIconList])
},
}
}
</script>
<style lang="less" scoped>
.nodeIconToolbar {
position: fixed;
z-index: 2000;
width: 210px;
max-height: 170px;
background: #fff;
border: 1px solid rgba(0, 0, 0, 0.06);
border-radius: 8px;
box-shadow: 0 2px 16px 0 rgba(0, 0, 0, 0.06);
display: flex;
flex-direction: column;
overflow: hidden;
.iconListBox {
width: 100%;
height: 180px;
overflow-y: auto;
padding: 10px;
.icon {
width: 24px;
height: 24px;
margin: 5px;
cursor: pointer;
position: relative;
float: left;
/deep/ img {
width: 100%;
height: 100%;
}
/deep/ svg {
width: 100%;
height: 100%;
}
&.selected {
&::after {
content: '';
position: absolute;
left: -4px;
top: -4px;
width: 28px;
height: 28px;
border-radius: 50%;
border: 2px solid #409eff;
}
}
}
}
.btnBox {
width: 100%;
height: 30px;
display: flex;
justify-content: center;
align-items: center;
border-top: 1px solid #eee;
flex-shrink: 0;
.btn {
cursor: pointer;
color: rgba(26, 26, 26, 0.8);
}
}
}
</style>

View File

@ -239,6 +239,7 @@ export default {
showNodeIcon() {
// this.$bus.$emit('showNodeIcon')
this.$bus.$emit('close_node_icon_toolbar')
this.setActiveSidebar('nodeIconSidebar')
},