mind-map/web/src/pages/Edit/components/Navigator.vue
2024-02-26 16:50:00 +08:00

185 lines
3.9 KiB
Vue

<template>
<div
v-if="showMiniMap"
class="navigatorBox"
:class="{ isDark: isDark }"
ref="navigatorBox"
:style="{ width: width + 'px' }"
@mousedown="onMousedown"
@mousemove="onMousemove"
@mouseup="onMouseup"
>
<div
class="svgBox"
ref="svgBox"
:style="{
transform: `scale(${svgBoxScale})`,
left: svgBoxLeft + 'px',
top: svgBoxTop + 'px'
}"
>
<img :src="mindMapImg" @mousedown.prevent />
</div>
<div class="windowBox" :style="viewBoxStyle"></div>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
props: {
mindMap: {
type: Object
}
},
data() {
return {
showMiniMap: false,
timer: null,
boxWidth: 0,
boxHeight: 0,
svgBoxScale: 1,
svgBoxLeft: 0,
svgBoxTop: 0,
viewBoxStyle: {
left: 0,
top: 0,
bottom: 0,
right: 0
},
mindMapImg: '',
width: 0,
setSizeTimer: null
}
},
computed: {
...mapState({
isDark: state => state.localConfig.isDark
})
},
mounted() {
this.setSize()
window.addEventListener('resize', this.setSize)
this.$bus.$on('toggle_mini_map', this.toggle_mini_map)
this.$bus.$on('data_change', this.data_change)
this.$bus.$on('view_data_change', this.data_change)
this.$bus.$on('node_tree_render_end', this.data_change)
},
destroyed() {
window.removeEventListener('resize', this.setSize)
this.$bus.$off('toggle_mini_map', this.toggle_mini_map)
this.$bus.$off('data_change', this.data_change)
this.$bus.$off('view_data_change', this.data_change)
this.$bus.$off('node_tree_render_end', this.data_change)
},
methods: {
// 切换显示小地图
toggle_mini_map(show) {
this.showMiniMap = show
this.$nextTick(() => {
if (this.$refs.navigatorBox) {
this.init()
}
if (this.$refs.svgBox) {
this.drawMiniMap()
}
})
},
// 思维导图数据改变,更新小地图
data_change() {
if (!this.showMiniMap) {
return
}
clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.drawMiniMap()
}, 500)
},
// 计算容器宽度
setSize() {
clearTimeout(this.setSizeTimer)
this.setSizeTimer = setTimeout(() => {
this.width = Math.min(window.innerWidth - 80, 370)
this.$nextTick(() => {
if (this.showMiniMap) {
this.init()
this.drawMiniMap()
}
})
}, 300)
},
// 获取宽高
init() {
let { width, height } = this.$refs.navigatorBox.getBoundingClientRect()
this.boxWidth = width
this.boxHeight = height
},
drawMiniMap() {
let {
getImgUrl,
viewBoxStyle,
miniMapBoxScale,
miniMapBoxLeft,
miniMapBoxTop
} = this.mindMap.miniMap.calculationMiniMap(this.boxWidth, this.boxHeight)
// 渲染到小地图
getImgUrl(img => {
this.mindMapImg = img
})
this.viewBoxStyle = viewBoxStyle
this.svgBoxScale = miniMapBoxScale
this.svgBoxLeft = miniMapBoxLeft
this.svgBoxTop = miniMapBoxTop
},
onMousedown(e) {
this.mindMap.miniMap.onMousedown(e)
},
onMousemove(e) {
this.mindMap.miniMap.onMousemove(e)
},
onMouseup(e) {
this.mindMap.miniMap.onMouseup(e)
}
}
}
</script>
<style lang="less" scoped>
.navigatorBox {
position: absolute;
height: 220px;
background-color: #fff;
bottom: 80px;
right: 70px;
box-shadow: 0 0 16px #989898;
border-radius: 4px;
border: 1px solid #eee;
cursor: pointer;
user-select: none;
&.isDark {
background-color: #262a2e;
}
.svgBox {
position: absolute;
left: 0;
transform-origin: left top;
}
.windowBox {
position: absolute;
border: 2px solid rgb(238, 69, 69);
transition: all 0.3s;
}
}
</style>