vue3 前端 引入 markmap 思维导图,通过markdown解析成思维导图实现思路及方法
1.下载插件
npm i --save-dev @types/file-saver
npm install file-saver
npm install html-to-image
npm install markmap-lib
npm install markmap-view
npm install markmap-common
2.创建页面
<template>
<!-- 思维导图预览 -->
<div class="mind">
<div class="controls">
<button class="btn" @click="zoomIn">放大</button>
<button class="btn" @click="zoomOut">缩小</button>
<button class="btn" @click="fitToScreen">适应屏幕</button>
<button class="btn" @click="onSave">下载</button>
</div>
<div class="svg-container">
<svg ref="svgRef"></svg>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, watch, onMounted, onUpdated } from 'vue';
import { Transformer } from 'markmap-lib';
import { Markmap } from 'markmap-view';
import * as htmlToImage from 'html-to-image';
import { saveAs } from 'file-saver';
const transformer = new Transformer();
// 存储 Markmap 实例和 SVG 引用
const mm = ref();
const svgRef = ref();
const props = defineProps({
mapVla: {
type: String, // 接收父组件传递的 mapVla 作为 prop
default: () => {}
}
});
// 放大和缩小功能
const zoomIn = () => mm.value?.rescale(1.25);
const zoomOut = () => mm.value?.rescale(0.8);
// 将思维导图适应屏幕
const fitToScreen = () => mm.value?.fit();
// 保存思维导图为图片
const onSave = async () => {
if (svgRef.value) {
const dataUrl = await htmlToImage.toPng(svgRef.value, {
backgroundColor: 'white', // 设置下载时的背景颜色为白色
style: {
color: 'black' // 设置下载时的文字颜色为黑色
}
});
saveAs(dataUrl, 'markmap.png'); // 保存为 PNG 文件
}
};
// 根据传入的 initValue 更新思维导图
const update = (initValue: string) => {
if (mm.value) {
const { root } = transformer.transform(initValue);
mm.value.setData(root);
mm.value.fit();
}
};
// 监听 mapVla 的变化,每当 mapVla 变化时重新更新思维导图
watch(
() => props.mapVla,
(newMapVla) => {
update(newMapVla); // 更新思维导图
fitToScreen();
},
{ immediate: true, deep: true }
);
// 组件挂载时初始化思维导图
onMounted(() => {
mm.value = Markmap.create(svgRef.value);
update(props.mapVla); // 初次渲染时根据 mapVla 渲染思维导图
});
onUpdated(() => update(props.mapVla)); // 每当 mapVla 更新时重新渲染
</script>
<style scoped lang="scss">
.mind {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
.svg-container {
flex: 1;
svg {
width: 100%;
height: 100%;
}
}
.controls {
display: flex;
justify-content: flex-end;
align-items: center;
gap: 15px;
margin-top: 10px;
padding-right: 20px;
.btn {
padding: 10px 20px;
font-size: 14px;
background-color: #615ced;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s ease;
}
.btn:hover {
background-color: #4a52c3; /* 稍微偏蓝且比原来深一些 */
transform: translateY(-2px);
}
.btn:active {
background-color: #3b45a1; /* 更深的蓝色,增加差异 */
transform: translateY(1px);
}
}
}
</style>
3.引用组件
<div class="chatMap" v-if="activeInput === '4'" :style="summaryStyle">
<Previewmap :mapVla="mapVla" />
</div>
推荐阅读:
扫描二维码,在手机上阅读