Navigator
This commit is contained in:
parent
533d2e5cac
commit
6d3bf694c1
@ -18,7 +18,6 @@
|
|||||||
"katex": "^0.16.9",
|
"katex": "^0.16.9",
|
||||||
"simple-mind-map-plugin-themes": "^1.0.0",
|
"simple-mind-map-plugin-themes": "^1.0.0",
|
||||||
"@toast-ui/editor": "^3.1.5",
|
"@toast-ui/editor": "^3.1.5",
|
||||||
"axios": "^1.7.9",
|
|
||||||
"codemirror": "^5.65.16"
|
"codemirror": "^5.65.16"
|
||||||
},
|
},
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
import tailwindConfig from './tailwind.config';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
plugins: {
|
|
||||||
...(process.env.NODE_ENV === 'production' ? { cssnano: {} } : {}),
|
|
||||||
autoprefixer: {},
|
|
||||||
tailwindcss: { config: tailwindConfig },
|
|
||||||
'tailwindcss/nesting': {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
299
web3/packages/mind-map/src/components/Navigator.vue
Normal file
299
web3/packages/mind-map/src/components/Navigator.vue
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-if="showMiniMap"
|
||||||
|
class="navigatorBox"
|
||||||
|
:class="{ isDark: isDark }"
|
||||||
|
ref="navigatorBoxRef"
|
||||||
|
:style="{ width: width + 'px' }"
|
||||||
|
@mousedown="onMousedown"
|
||||||
|
@mousemove="onMousemove"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="svgBox"
|
||||||
|
ref="svgBoxRef"
|
||||||
|
:style="{
|
||||||
|
transform: `scale(${svgBoxScale})`,
|
||||||
|
left: svgBoxLeft + 'px',
|
||||||
|
top: svgBoxTop + 'px',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<img :src="mindMapImg" @mousedown.prevent />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="windowBox"
|
||||||
|
:style="viewBoxStyle"
|
||||||
|
:class="{ withTransition: withTransition }"
|
||||||
|
@mousedown.stop="onViewBoxMousedown"
|
||||||
|
@mousemove="onViewBoxMousemove"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, onUnmounted, computed, nextTick, watch } from "vue";
|
||||||
|
import { useMindMapStore } from "../index";
|
||||||
|
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
|
||||||
|
const { getMindMapInstance } = useMindMapStore();
|
||||||
|
const { isDark, showMiniMap } = storeToRefs(useMindMapStore());
|
||||||
|
|
||||||
|
const timer = ref(null);
|
||||||
|
|
||||||
|
const boxWidth = ref(0);
|
||||||
|
const boxHeight = ref(0);
|
||||||
|
const svgBoxScale = ref(1);
|
||||||
|
const svgBoxLeft = ref(0);
|
||||||
|
const svgBoxTop = ref(0);
|
||||||
|
|
||||||
|
const viewBoxStyle = ref({
|
||||||
|
left: "0px", // 确保初始值为字符串以匹配后续更新
|
||||||
|
top: "0px",
|
||||||
|
bottom: "0px",
|
||||||
|
right: "0px",
|
||||||
|
});
|
||||||
|
|
||||||
|
const mindMapImg = ref("");
|
||||||
|
|
||||||
|
const width = ref(0);
|
||||||
|
const setSizeTimer = ref(null);
|
||||||
|
const withTransition = ref(true);
|
||||||
|
|
||||||
|
const navigatorBoxRef = ref(null);
|
||||||
|
const svgBoxRef = ref(null);
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
if (!navigatorBoxRef.value) return;
|
||||||
|
const rect = navigatorBoxRef.value.getBoundingClientRect();
|
||||||
|
boxWidth.value = rect.width;
|
||||||
|
boxHeight.value = rect.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawMiniMap() {
|
||||||
|
const currentMindMap = getMindMapInstance();
|
||||||
|
if (
|
||||||
|
!currentMindMap ||
|
||||||
|
!currentMindMap.miniMap ||
|
||||||
|
!boxWidth.value ||
|
||||||
|
!boxHeight.value
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
try {
|
||||||
|
const calculationResult = currentMindMap.miniMap.calculationMiniMap(
|
||||||
|
boxWidth.value,
|
||||||
|
boxHeight.value
|
||||||
|
);
|
||||||
|
if (!calculationResult) return;
|
||||||
|
|
||||||
|
const {
|
||||||
|
getImgUrl,
|
||||||
|
viewBoxStyle: newViewBoxStyle,
|
||||||
|
miniMapBoxScale: newMiniMapBoxScale,
|
||||||
|
miniMapBoxLeft: newMiniMapBoxLeft,
|
||||||
|
miniMapBoxTop: newMiniMapBoxTop,
|
||||||
|
} = calculationResult;
|
||||||
|
|
||||||
|
if (getImgUrl && typeof getImgUrl === "function") {
|
||||||
|
getImgUrl((img) => {
|
||||||
|
mindMapImg.value = img;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (newViewBoxStyle) viewBoxStyle.value = newViewBoxStyle;
|
||||||
|
if (newMiniMapBoxScale !== undefined)
|
||||||
|
svgBoxScale.value = newMiniMapBoxScale;
|
||||||
|
if (newMiniMapBoxLeft !== undefined) svgBoxLeft.value = newMiniMapBoxLeft;
|
||||||
|
if (newMiniMapBoxTop !== undefined) svgBoxTop.value = newMiniMapBoxTop;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error drawing minimap:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggle_mini_map(show) {
|
||||||
|
showMiniMap.value = show; // 更新 store 中的状态
|
||||||
|
// nextTick 逻辑移至 watch
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => showMiniMap.value,
|
||||||
|
(isShown) => {
|
||||||
|
if (isShown) {
|
||||||
|
nextTick(() => {
|
||||||
|
navigatorBoxRef.value && init();
|
||||||
|
svgBoxRef.value && drawMiniMap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
function data_change() {
|
||||||
|
if (!showMiniMap.value) {
|
||||||
|
// 使用 store 中的状态
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clearTimeout(timer.value);
|
||||||
|
timer.value = setTimeout(() => {
|
||||||
|
drawMiniMap();
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSize() {
|
||||||
|
clearTimeout(setSizeTimer.value);
|
||||||
|
setSizeTimer.value = setTimeout(() => {
|
||||||
|
width.value = Math.min(window.innerWidth - 80, 370);
|
||||||
|
nextTick(() => {
|
||||||
|
if (showMiniMap.value && navigatorBoxRef.value) {
|
||||||
|
init();
|
||||||
|
drawMiniMap();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMousedown(e) {
|
||||||
|
const currentMindMap = getMindMapInstance();
|
||||||
|
if (
|
||||||
|
currentMindMap &&
|
||||||
|
currentMindMap.miniMap &&
|
||||||
|
typeof currentMindMap.miniMap.onMousedown === "function"
|
||||||
|
) {
|
||||||
|
currentMindMap.miniMap.onMousedown(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMousemove(e) {
|
||||||
|
const currentMindMap = getMindMapInstance();
|
||||||
|
if (
|
||||||
|
currentMindMap &&
|
||||||
|
currentMindMap.miniMap &&
|
||||||
|
typeof currentMindMap.miniMap.onMousemove === "function"
|
||||||
|
) {
|
||||||
|
currentMindMap.miniMap.onMousemove(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMouseup(e) {
|
||||||
|
if (!withTransition.value) {
|
||||||
|
withTransition.value = true;
|
||||||
|
}
|
||||||
|
const currentMindMap = getMindMapInstance();
|
||||||
|
if (
|
||||||
|
currentMindMap &&
|
||||||
|
currentMindMap.miniMap &&
|
||||||
|
typeof currentMindMap.miniMap.onMouseup === "function"
|
||||||
|
) {
|
||||||
|
currentMindMap.miniMap.onMouseup(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onViewBoxMousedown(e) {
|
||||||
|
const currentMindMap = getMindMapInstance();
|
||||||
|
if (
|
||||||
|
currentMindMap &&
|
||||||
|
currentMindMap.miniMap &&
|
||||||
|
typeof currentMindMap.miniMap.onViewBoxMousedown === "function"
|
||||||
|
) {
|
||||||
|
currentMindMap.miniMap.onViewBoxMousedown(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onViewBoxMousemove(e) {
|
||||||
|
const currentMindMap = getMindMapInstance();
|
||||||
|
if (
|
||||||
|
currentMindMap &&
|
||||||
|
currentMindMap.miniMap &&
|
||||||
|
typeof currentMindMap.miniMap.onViewBoxMousemove === "function"
|
||||||
|
) {
|
||||||
|
currentMindMap.miniMap.onViewBoxMousemove(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onViewBoxPositionChange({ left, right, top, bottom }) {
|
||||||
|
withTransition.value = false;
|
||||||
|
viewBoxStyle.value.left = left;
|
||||||
|
viewBoxStyle.value.right = right;
|
||||||
|
viewBoxStyle.value.top = top;
|
||||||
|
viewBoxStyle.value.bottom = bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
setSize();
|
||||||
|
window.addEventListener("resize", setSize);
|
||||||
|
window.addEventListener("mouseup", onMouseup);
|
||||||
|
|
||||||
|
// 事件总线监听 (请根据您的项目调整)
|
||||||
|
// eventBus.on('toggle_mini_map', toggle_mini_map);
|
||||||
|
// eventBus.on('data_change', data_change);
|
||||||
|
// eventBus.on('view_data_change', data_change); // Vue2 中 view_data_change 和 data_change 调用相同处理函数
|
||||||
|
// eventBus.on('node_tree_render_end', data_change);
|
||||||
|
|
||||||
|
// watch(getMindMapInstance(), (newInstance) => {
|
||||||
|
// if (newInstance && typeof newInstance.on === 'function') {
|
||||||
|
// newInstance.on(
|
||||||
|
// 'mini_map_view_box_position_change',
|
||||||
|
// onViewBoxPositionChange
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }, { immediate: true });
|
||||||
|
|
||||||
|
// 如果初始时就需要显示小地图,可以在这里调用 toggle_mini_map(true)
|
||||||
|
// 或者通过外部事件触发
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
window.removeEventListener("resize", setSize);
|
||||||
|
window.removeEventListener("mouseup", onMouseup);
|
||||||
|
|
||||||
|
// 事件总线解绑 (请根据您的项目调整)
|
||||||
|
// eventBus.off('toggle_mini_map', toggle_mini_map);
|
||||||
|
// eventBus.off('data_change', data_change);
|
||||||
|
// eventBus.off('view_data_change', data_change);
|
||||||
|
// eventBus.off('node_tree_render_end', data_change);
|
||||||
|
|
||||||
|
const currentMindMap = getMindMapInstance();
|
||||||
|
if (currentMindMap && typeof currentMindMap.off === "function") {
|
||||||
|
currentMindMap.off(
|
||||||
|
"mini_map_view_box_position_change",
|
||||||
|
onViewBoxPositionChange
|
||||||
|
);
|
||||||
|
}
|
||||||
|
clearTimeout(timer.value);
|
||||||
|
clearTimeout(setSizeTimer.value);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.navigatorBox {
|
||||||
|
position: absolute;
|
||||||
|
height: 220px;
|
||||||
|
background-color: #fff;
|
||||||
|
bottom: 24px;
|
||||||
|
right: 24px;
|
||||||
|
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;
|
||||||
|
top: 0;
|
||||||
|
transform-origin: left top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.windowBox {
|
||||||
|
position: absolute;
|
||||||
|
border: 2px solid rgb(238, 69, 69);
|
||||||
|
background-color: rgba(238, 69, 69, 0.2);
|
||||||
|
|
||||||
|
&.withTransition {
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -7,11 +7,13 @@ import ExportPDF from 'simple-mind-map/src/plugins/ExportPDF'
|
|||||||
import ExportXMind from 'simple-mind-map/src/plugins/ExportXMind'
|
import ExportXMind from 'simple-mind-map/src/plugins/ExportXMind'
|
||||||
import Export from 'simple-mind-map/src/plugins/Export'
|
import Export from 'simple-mind-map/src/plugins/Export'
|
||||||
import MindMapLayoutPro from 'simple-mind-map/src/plugins/MindMapLayoutPro'
|
import MindMapLayoutPro from 'simple-mind-map/src/plugins/MindMapLayoutPro'
|
||||||
|
import MiniMap from 'simple-mind-map/src/plugins/MiniMap'
|
||||||
// import RichText from 'simple-mind-map/src/plugins/RichText'
|
// import RichText from 'simple-mind-map/src/plugins/RichText'
|
||||||
|
|
||||||
|
|
||||||
export function usePlugins(MindMapConstructor: typeof MindMap) {
|
export function usePlugins(MindMapConstructor: typeof MindMap) {
|
||||||
// 注册插件
|
// 注册插件
|
||||||
|
MindMapConstructor.usePlugin(MiniMap);
|
||||||
MindMapConstructor.usePlugin(ExportPDF);
|
MindMapConstructor.usePlugin(ExportPDF);
|
||||||
MindMapConstructor.usePlugin(ExportXMind);
|
MindMapConstructor.usePlugin(ExportXMind);
|
||||||
MindMapConstructor.usePlugin(Export);
|
MindMapConstructor.usePlugin(Export);
|
||||||
|
|||||||
@ -39,6 +39,12 @@ function defineStoreImplementation() {
|
|||||||
|
|
||||||
const mindMapData = ref(null);
|
const mindMapData = ref(null);
|
||||||
|
|
||||||
|
// 是否小地图
|
||||||
|
const showMiniMap = ref(true);
|
||||||
|
|
||||||
|
// 是否深色
|
||||||
|
const isDark = ref(false);
|
||||||
|
|
||||||
// 激活状态节点
|
// 激活状态节点
|
||||||
const activeNodes = shallowRef<MindMapNode[]>([]);
|
const activeNodes = shallowRef<MindMapNode[]>([]);
|
||||||
|
|
||||||
@ -136,6 +142,8 @@ function defineStoreImplementation() {
|
|||||||
mindMapData,
|
mindMapData,
|
||||||
activeNodes,
|
activeNodes,
|
||||||
currentLayout,
|
currentLayout,
|
||||||
|
showMiniMap,
|
||||||
|
isDark,
|
||||||
|
|
||||||
getMindMapInstance,
|
getMindMapInstance,
|
||||||
importFile,
|
importFile,
|
||||||
|
|||||||
4
web3/packages/mind-map/src/types/index.d.ts
vendored
4
web3/packages/mind-map/src/types/index.d.ts
vendored
@ -35,4 +35,8 @@ declare module 'simple-mind-map/src/plugins/RichText' {
|
|||||||
import RichText from 'simple-mind-map/types/src/plugins/RichText';
|
import RichText from 'simple-mind-map/types/src/plugins/RichText';
|
||||||
export default RichText;
|
export default RichText;
|
||||||
}
|
}
|
||||||
|
declare module 'simple-mind-map/src/plugins/MiniMap' {
|
||||||
|
import MiniMap from 'simple-mind-map/types/src/plugins/MiniMap';
|
||||||
|
export default MiniMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
<div class="relative w-full h-full border">
|
<div class="relative w-full h-full border">
|
||||||
<!-- 操作拦 -->
|
<!-- 操作拦 -->
|
||||||
<ToolBar />
|
<ToolBar />
|
||||||
|
<!-- 导航器 -->
|
||||||
|
<Navigator />
|
||||||
<div
|
<div
|
||||||
class="w-full h-full mindMapContainer"
|
class="w-full h-full mindMapContainer"
|
||||||
id="mindMapContainer"
|
id="mindMapContainer"
|
||||||
@ -13,6 +15,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref } from "vue";
|
||||||
import ToolBar from "../components/ToolBar.vue";
|
import ToolBar from "../components/ToolBar.vue";
|
||||||
|
import Navigator from "../components/Navigator.vue";
|
||||||
|
|
||||||
import { useMindMapStore } from "../store/index";
|
import { useMindMapStore } from "../store/index";
|
||||||
import type MindMapNode from "simple-mind-map/types/src/core/render/node/MindMapNode";
|
import type MindMapNode from "simple-mind-map/types/src/core/render/node/MindMapNode";
|
||||||
|
|||||||
@ -1,50 +0,0 @@
|
|||||||
import type { Config } from 'tailwindcss'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
content: [
|
|
||||||
"./index.html",
|
|
||||||
"./src/**/*.{vue,js,ts,jsx,tsx,mdx}",
|
|
||||||
],
|
|
||||||
theme: {
|
|
||||||
extend: {
|
|
||||||
colors: {
|
|
||||||
border: "rgb(var(--border) / <alpha-value>)",
|
|
||||||
input: "rgb(var(--input) / <alpha-value>)",
|
|
||||||
ring: "rgb(var(--ring) / <alpha-value>)",
|
|
||||||
background: "rgb(var(--background) / <alpha-value>)",
|
|
||||||
foreground: "rgb(var(--foreground) / <alpha-value>)",
|
|
||||||
primary: {
|
|
||||||
DEFAULT: "rgb(var(--primary) / <alpha-value>)",
|
|
||||||
foreground: "rgb(var(--primary-foreground) / <alpha-value>)",
|
|
||||||
hover: "rgb(var(--primary-hover) / <alpha-value>)",
|
|
||||||
active: "rgb(var(--primary-active) / <alpha-value>)",
|
|
||||||
},
|
|
||||||
secondary: {
|
|
||||||
DEFAULT: "rgb(var(--secondary) / <alpha-value>)",
|
|
||||||
foreground: "rgb(var(--secondary-foreground) / <alpha-value>)",
|
|
||||||
},
|
|
||||||
destructive: {
|
|
||||||
DEFAULT: "rgb(var(--destructive) / <alpha-value>)",
|
|
||||||
foreground: "rgb(var(--destructive-foreground) / <alpha-value>)",
|
|
||||||
},
|
|
||||||
muted: {
|
|
||||||
DEFAULT: "rgb(var(--muted) / <alpha-value>)",
|
|
||||||
foreground: "rgb(var(--muted-foreground) / <alpha-value>)",
|
|
||||||
},
|
|
||||||
accent: {
|
|
||||||
DEFAULT: "rgb(var(--accent) / <alpha-value>)",
|
|
||||||
foreground: "rgb(var(--accent-foreground) / <alpha-value>)",
|
|
||||||
},
|
|
||||||
popover: {
|
|
||||||
DEFAULT: "rgb(var(--popover) / <alpha-value>)",
|
|
||||||
foreground: "rgb(var(--popover-foreground) / <alpha-value>)",
|
|
||||||
},
|
|
||||||
card: {
|
|
||||||
DEFAULT: "rgb(var(--card) / <alpha-value>)",
|
|
||||||
foreground: "rgb(var(--card-foreground) / <alpha-value>)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [],
|
|
||||||
} satisfies Config
|
|
||||||
0
web3/packages/mind-map/vite.config.ts
Normal file
0
web3/packages/mind-map/vite.config.ts
Normal file
Loading…
x
Reference in New Issue
Block a user