Vue3 TS setup 引入 markmap 思维导图,通过markdown解析成思维导图,集成到自己项目中

【前言】%(&(&……()*

最近刚好做了个项目,给大家分享一个Vue3 TS setup 如何引入 markmap 思维导图,markmap可以通过markdown解析成思维导图。我们如何将它集成到自己项目中?

【看图】还是先看图再继续

在这里插入图片描述

【文档】官方也有文档,如果这个帖子沉了,大家可以直接去官方找最新的

  • 官网文档 http://markmap.js.org

  • 官方示例 https://markmap.js.org/repl

【实战】如何继承到Vue3项目中

  1. 添加依赖
pnpm add markmap-lib
pnpm add markmap-view

... tailwindcss
  1. 创建vue文件
<template>
  <div class="flex-1">
    <textarea class="w-full h-full border border-gray-400" v-model="value" />
  </div>
  <svg class="flex-1" ref="svgRef" />
</template>

<script lang="ts" setup>
import { ref, onMounted, onUpdated } from 'vue';
import { Transformer } from 'markmap-lib';
import { Markmap } from 'markmap-view/dist/index.esm';

const transformer = new Transformer();
const initValue = `# 思维导图
1. 标题1
 - 子标题1
 - 子标题2
3. 标题2
4. 标题3
`;
const mm = ref()
const value = ref('')
const svgRef = ref()
const update = () =>{
	 const { root } = transformer.transform(value.value);
      mm.value.setData(root);
      mm.value.fit();
}

watch(()=>value.value,(n)=>{
	// 监听输入变化更新思维导图
	update()
})
onMounted(()=>{
	// 初始化markmap思维导图
	mm.value = Markmap.create(svgRef.value);
	value.value = initValue.value
	// 更新思维导图渲染
    update();
})
</script>

ps: 可以集成到chatgpt,具体怎么搞大家先自己玩,路子很多也很野

【结语】纯本人手写,没有科技加持,点赞再走

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
以下是一个使用 Vue3 和 TypeScript 实现的 D3 思维导图的示例代码,同时自定义了无限嵌套的功能: ```vue <template> <div ref="svgContainer"></div> </template> <script lang="ts"> import { defineComponent, onMounted, ref } from 'vue'; import * as d3 from 'd3'; export default defineComponent({ setup() { const svgContainer = ref<HTMLElement | null>(null); let svg: d3.Selection<SVGSVGElement, unknown, null, undefined> | undefined; let zoom: d3.ZoomBehavior<Element, unknown> | undefined; let g: d3.Selection<SVGGElement, unknown, null, undefined> | undefined; let root: d3.HierarchyNode<unknown> | undefined; const data = { name: 'root', children: [ { name: 'child1' }, { name: 'child2', children: [{ name: 'grandchild1' }, { name: 'grandchild2' }] }, ], }; const treeLayout = d3.tree().size([400, 400]); // 递归遍历树结构,为每个节点添加 id 和 parent 属性 const addIdAndParent = (node: d3.HierarchyNode<unknown>, parentId?: string) => { node.id = `${node.data.name}_${Math.random().toString(16).slice(2)}`; node.parentId = parentId; if (node.children) { node.children.forEach((child) => addIdAndParent(child, node.id)); } }; // 自定义的无限嵌套函数,每次嵌套时在当前节点下添加两个子节点 const nest = (node: d3.HierarchyNode<unknown>) => { const id1 = `${node.id}_1`; const id2 = `${node.id}_2`; node.children = [ { name: `child1_${id1}` }, { name: `child2_${id2}`, children: [{ name: `grandchild1_${id1}` }, { name: `grandchild2_${id2}` }] }, ]; node.children.forEach((child) => { child.id = `${child.name}_${Math.random().toString(16).slice(2)}`; child.parentId = node.id; }); return node; }; const update = (source: d3.HierarchyNode<unknown>) => { // 更新树结构 const nodes = treeLayout(root!).descendants(); const links = treeLayout(root!).links(); // 更新链接 const link = g!.selectAll('.link').data(links, (d) => (d as any).target.id); link.enter().append('path').attr('class', 'link').attr('d', d3.linkHorizontal().x((d: any) => d.y).y((d: any) => d.x)); link.transition().attr('d', d3.linkHorizontal().x((d: any) => d.y).y((d: any) => d.x)); link.exit().remove(); // 更新节点 const node = g!.selectAll('.node').data(nodes, (d) => (d as any).id); const nodeEnter = node.enter().append('g').attr('class', 'node').attr('transform', () => `translate(${source.y0},${source.x0})`); nodeEnter.append('circle').attr('r', 10).style('fill', '#fff').style('stroke', '#000'); nodeEnter.append('text').attr('dy', '0.35em').attr('x', (d) => (d.children ? -13 : 13)).style('text-anchor', (d) => (d.children ? 'end' : 'start')).text((d) => d.data.name); const nodeUpdate = nodeEnter.merge(node); nodeUpdate.transition().attr('transform', (d) => `translate(${d.y},${d.x})`); node.exit().transition().attr('transform', () => `translate(${source.y},${source.x})`).remove(); nodes.forEach((d) => { d.x0 = d.x; d.y0 = d.y; }); }; const init = () => { svg = d3.select(svgContainer.value).append('svg').attr('width', '100%').attr('height', '100%'); zoom = d3.zoom().scaleExtent([0.1, 10]).on('zoom', () => { g!.attr('transform', d3.event.transform); }); svg.call(zoom); g = svg.append('g').attr('transform', 'translate(50, 50)'); root = d3.hierarchy(data, (d) => d.children); addIdAndParent(root!); update(root!); // 点击节点时无限嵌套 svg.selectAll('.node').on('click', (d: d3.HierarchyNode<unknown>) => { nest(d); update(d); zoom?.transform(svg!, d3.zoomIdentity.translate(50, 50).scale(1)); }); }; onMounted(() => { init(); }); return { svgContainer, }; }, }); </script> <style> .node { cursor: pointer; } </style> ``` 在这个示例,我们使用了 D3 的树形布局来排列思维导图的节点,使用递归函数遍历树结构为每个节点添加了 id 和 parentId 属性,并且使用了 D3 的选择集和过渡来更新节点和链接的位置。同时,在点击节点时使用自定义的无限嵌套函数实现了无限嵌套的功能。 需要注意的是,这个示例代码只是一个比较简单的实现,具体的实现方式和界面样式还需要根据具体的需求进行调整。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值