php 生成思维导图,JavaScript如何生成思维导图(mindmap)

JavaScript如何生成思维导图(mindmap)

一、总结

一句话总结:可以直接用gojs

gojs

二、一个用JavaScript生成思维导图(mindmap)的github repo(转)

转自:一个用JavaScript生成思维导图(mindmap)的github repo - JerryWangSAP - 博客园

https://www.cnblogs.com/sap-jerry/p/8969516.html

作者的readme写得很简单。

今天有同事问作者提供的例子到底怎么跑。这里我就写一个更详细的步骤出来。

2104ae11d366c6b10280b43b0cf293ff.png

首先查看example.parse.js的内容:

var fs = require('fs');

var parse = require('../parse.markdown');

var transform = require('../transform.headings');

var text = fs.readFileSync('gtor.md', 'utf-8');

var headings = parse(text);

var root = transform(headings);

console.log(root);

fs.writeFileSync('gtor.json', JSON.stringify(root));

使用nodejs命名node example.parse.js执行这段代码:代码读取包含思维导图的本地文件gtor.md, 解析并转换生成本地文件gtor.jso

<think>我们遇到了一个问题:markmap-view只有TypeScript版本,而我们想要在Java应用中使用它生成思维导图。由于我们无法直接在Java中运行TypeScript,我们需要一个解决方案来将markmap集成到Java应用中。解决方案思路:1.使用JavaScript引擎(如Nashorn或GraalVM)在Java中执行JavaScript代码,但markmap依赖于DOM和浏览器环境,这在服务器端JavaScript引擎中不可用。2.使用无头浏览器(如Puppeteer)在后台生成思维导图的图片或HTML,然后返回给客户端。但Puppeteer是Node.js库,需要从Java调用Node.js进程。3.将markmap的渲染工作放在客户端(浏览器),服务器只提供数据(JSON格式)。这样,我们只需要在Java应用中生成包含markmap库的HTML文件,并将数据嵌入其中。考虑到复杂性和可行性,我们选择第三种方案:在服务器端生成一个自包含的HTML文件,该文件使用markmap库在客户端渲染思维导图。但是,之前我们遇到了CDN加载失败的问题,因此我们需要一个更可靠的方式。我们可以:a)将markmap的库文件作为本地资源嵌入(内联或从本地服务器提供)b)使用备用CDN并添加重试机制这里我们采用内联库文件的方式,生成一个完全自包含的HTML文件,这样就不需要网络加载库文件。步骤:1.下载markmap-view和d3的UMD版本(或minified版本)的JavaScript文件。2.在生成HTML时,将这两个库的代码内联到HTML的<script>标签中。3.在HTML中编写初始化代码,使用内嵌的JSON数据渲染思维导图。注意:markmap-view依赖于d3,所以我们需要先内联d3,再内联markmap-view。具体实现:我们将编写一个Java方法,该方法接收Markdown内容(或已经转换好的markmap的JSON数据),然后生成一个包含内联库代码和初始化脚本的HTML字符串,并保存为文件。由于我们无法直接从Java运行TypeScript,我们使用已经构建好的JavaScript文件(从CDN下载)。示例代码:1.从指定的URL下载d3和markmap-view的JS文件内容(作为字符串)。2.构建HTML模板,将下载的JS内容内联到<script>标签中。3.将数据(JSON字符串)嵌入到HTML的初始化脚本中。但是,我们也可以预先下载好这些库文件,并作为字符串常量存储在Java类中(但这样会使类文件很大)。或者,我们可以将这些库文件放在resources目录下,在运行时读取。这里我们选择在运行时下载(或者我们可以将库文件放在classpath中,在应用启动时读取)。为了简单,我们使用从classpath读取的方式。假设我们已经将d3.min.js和markmap.min.js放在resources的lib目录下。步骤:1.创建工具类,读取classpath下的库文件内容为字符串。2.构建HTML字符串,包含:-样式-放置思维导图的div容器-内联d3库-内联markmap-view库-初始化脚本(使用内嵌的JSON数据)但是,考虑到用户可能无法下载,我们也可以提供一种机制:如果无法从classpath读取,则从CDN下载(作为后备)。不过,为了简化,我们假设这些库文件已经作为资源打包在应用中。代码示例:我们将创建一个方法:generateHtml(StringjsonData,Stringd3JsContent,StringmarkmapJsContent)它返回一个包含内联库和初始化代码的HTML字符串。初始化代码示例://创建SVG容器constcontainer=document.getElementById('mindmap');constsvg=d3.select(container).append('svg');//设置尺寸svg.attr('width',container.clientWidth).attr('height',container.clientHeight);//创建Markmapconstmm=markmap.Markmap.create(svg.node(),null,data);//窗口大小变化时调整window.addEventListener('resize',()=>{svg.attr('width',container.clientWidth).attr('height',container.clientHeight);mm.fit();});注意:数据是直接作为JSON对象嵌入的,所以我们需要确保JSON字符串是有效的。但是,如果我们的输入是Markdown格式,我们还需要一个转换步骤(将Markdown转换为markmap的JSON格式)。这个转换可以在服务器端用Java实现,或者使用markmap的解析库(在JavaScript中)。由于我们已经在生成HTML时内联了markmap-view,它包含了markmap的Markdown解析器,所以我们可以在客户端进行转换。然而,为了减少客户端负担,我们可以在服务器端将Markdown转换为markmap的JSON格式。这里我们使用一个Java的Markdown解析库(如flexmark)来解析Markdown并生成类似markmap的JSON结构。但这需要了解markmap的JSON结构。或者,我们可以使用markmap的transform方法(在JavaScript中)在客户端转换。这样,我们只需要在初始化脚本中调用markmap.transform方法将Markdown文本转换为JSON数据。两种方式都可以,这里我们选择在服务器端生成JSON数据,因为这样更可控,并且可以避免在客户端解析大Markdown文件。因此,我们的输入是JSON数据(字符串形式),直接内嵌到HTML中。实现:步骤1:读取库文件内容(作为字符串)步骤2:构建HTML字符串考虑到库文件可能很大,内联后HTML文件会很大,但这样保证了单文件可运行。代码:我们将创建一个类MarkmapGenerator,它包含一个方法generateHtml(StringjsonData)返回HTML字符串。如果库文件在classpath中,我们可以这样读取:```javaStringd3Content=newString(Files.readAllBytes(Paths.get(getClass().getResource("/lib/d3.min.js").toURI())),StandardCharsets.UTF_8);StringmarkmapContent=newString(Files.readAllBytes(Paths.get(getClass().getResource("/lib/markmap.min.js").toURI())),StandardCharsets.UTF_8);```然后构建HTML。但是,如果资源文件不存在,我们可以提供后备方案(比如从CDN内联,但这样需要网络,而且生成的文件就不是自包含的了),所以我们要求必须将库文件放在classpath的lib目录下。完整代码示例:</think># 在 Java 应用中集成 Markmap 思维导图(纯 JavaScript/TypeScript 解决方案) ## 问题分析 您提到 "markmap-view 只有 ts",这指的是 Markmap 库是用 TypeScript 编写的,没有提供直接的 Java API。但我们可以通过以下方法在 Java 应用中集成 Markmap: 1. **服务器端渲染**:使用无头浏览器生成思维导图 2. **客户端渲染**:在 Java 应用中生成包含 Markmap 的 HTML 文件 3. **API 封装**:通过 Node.js 服务桥接 Java 和 Markmap 下面我将提供一个完整的客户端渲染解决方案,使用 Java 生成包含 Markmap 库的 HTML 文件,并嵌入思维导图数据。 ## 解决方案:Java 生成自包含的 Markmap HTML ### 1. 准备 Markmap 库文件 由于 Markmap 只有 TypeScript 版本,我们需要将其编译为 JavaScript 或使用预编译版本: ```java import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.net.URL; public class MarkmapLibraryManager { // 下载 Markmap 库文件 public static void downloadMarkmapLibraries(String outputDir) throws IOException { Path dir = Paths.get(outputDir); if (!Files.exists(dir)) { Files.createDirectories(dir); } // 下载 d3.js (v7) downloadFile("https://d3js.org/d3.v7.min.js", outputDir + "/d3.min.js"); // 下载 markmap-view (预编译版本) downloadFile("https://unpkg.com/[email protected]/dist/index.min.js", outputDir + "/markmap.min.js"); } private static void downloadFile(String url, String outputPath) throws IOException { try (InputStream in = new URL(url).openStream()) { Files.copy(in, Paths.get(outputPath), StandardCopyOption.REPLACE_EXISTING); System.out.println("Downloaded: " + url + " -> " + outputPath); } } // 读取库文件内容 public static String readLibraryFile(String path) throws IOException { return Files.readString(Paths.get(path)); } } ``` ### 2. Java 生成自包含 HTML ```java import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; public class MarkmapGenerator { // 生成包含 Markmap 的 HTML 文件 public static String generateMarkmapHtml(String markdownContent, String d3JsContent, String markmapJsContent) { // 将 Markdown 转换为 Markmap 所需的 JSON 格式 String jsonData = convertMarkdownToJson(markdownContent); return "<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + "<head>\n" + " <meta charset=\"UTF-8\">\n" + " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" + " <title>Markmap Visualization</title>\n" + " <style>\n" + " body {\n" + " margin: 0;\n" + " font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n" + " background-color: #f8f9fa;\n" + " }\n" + " #container {\n" + " display: flex;\n" + " flex-direction: column;\n" + " height: 100vh;\n" + " }\n" + " #toolbar {\n" + " padding: 10px 15px;\n" + " background-color: #2c3e50;\n" + " color: white;\n" + " display: flex;\n" + " justify-content: space-between;\n" + " align-items: center;\n" + " }\n" + " #mindmap {\n" + " flex-grow: 1;\n" + " background: white;\n" + " }\n" + " .btn {\n" + " background-color: #3498db;\n" + " color: white;\n" + " border: none;\n" + " padding: 8px 15px;\n" + " border-radius: 4px;\n" + " cursor: pointer;\n" + " font-size: 14px;\n" + " }\n" + " .btn:hover {\n" + " background-color: #2980b9;\n" + " }\n" + " </style>\n" + " <script>\n" + " // Inlined d3.js library\n" + d3JsContent + "\n" + " </script>\n" + " <script>\n" + " // Inlined markmap-view library\n" + markmapJsContent + "\n" + " </script>\n" + "</head>\n" + "<body>\n" + " <div id=\"container\">\n" + " <div id=\"toolbar\">\n" + " <h2>Java-Generated Mindmap</h2>\n" + " <div>\n" + " <button class=\"btn\" id=\"zoom-in\">Zoom In</button>\n" + " <button class=\"btn\" id=\"zoom-out\">Zoom Out</button>\n" + " <button class=\"btn\" id=\"reset\">Reset View</button>\n" + " </div>\n" + " </div>\n" + " <div id=\"mindmap\"></div>\n" + " </div>\n" + " \n" + " <script>\n" + " // Markmap data from Java\n" + " const markdownData = `" + markdownContent + "`;\n" + " \n" + " // Initialize Markmap\n" + " let markmapInstance;\n" + " \n" + " function initMarkmap() {\n" + " // Create SVG container\n" + " const container = d3.select('#mindmap');\n" + " container.selectAll('*').remove(); // Clear previous\n" + " const svg = container.append('svg');\n" + " \n" + " // Set dimensions\n" + " svg.attr('width', container.node().clientWidth)\n" + " .attr('height', container.node().clientHeight);\n" + " \n" + " // Transform Markdown to mindmap data\n" + " const { root } = markmap.transform.parse(markdownData);\n" + " \n" + " // Create Markmap\n" + " markmapInstance = markmap.Markmap.create(svg.node(), {\n" + " color: ['#3498db', '#2ecc71', '#e74c3c', '#f39c12'],\n" + " nodeMinHeight: 24,\n" + " spacingVertical: 8,\n" + " paddingX: 10,\n" + " duration: 500,\n" + " }, root);\n" + " \n" + " // Fit to view\n" + " markmapInstance.fit();\n" + " \n" + " // Add node click handler\n" + " svg.on('click', 'g', function(event, d) {\n" + " console.log('Node clicked:', d.data.content);\n" + " // Custom logic here\n" + " });\n" + " }\n" + " \n" + " // Handle window resize\n" + " window.addEventListener('resize', () => {\n" + " if (markmapInstance) {\n" + " const container = d3.select('#mindmap');\n" + " const svg = container.select('svg');\n" + " svg.attr('width', container.node().clientWidth)\n" + " .attr('height', container.node().clientHeight);\n" + " markmapInstance.fit();\n" + " }\n" + " });\n" + " \n" + " // Toolbar actions\n" + " document.getElementById('zoom-in').addEventListener('click', () => {\n" + " if (markmapInstance) markmapInstance.zoom(1.2);\n" + " });\n" + " \n" + " document.getElementById('zoom-out').addEventListener('click', () => {\n" + " if (markmapInstance) markmapInstance.zoom(0.8);\n" + " });\n" + " \n" + " document.getElementById('reset').addEventListener('click', () => {\n" + " if (markmapInstance) {\n" + " markmapInstance.fit();\n" + " markmapInstance.zoom(1);\n" + " }\n" + " });\n" + " \n" + " // Initialize on load\n" + " window.addEventListener('load', initMarkmap);\n" + " </script>\n" + "</body>\n" + "</html>"; } // 简化的 Markdown 转 JSON 转换器 private static String convertMarkdownToJson(String markdown) { // 实际应用中应使用更健壮的解析器 // 这里返回一个简单的 JSON 结构示例 return "{\"t\":\"root\",\"d\":0,\"v\":\"\",\"c\":[{\"t\":\"heading\",\"d\":1,\"v\":\"Java Generated Mindmap\"}]}"; } public static void main(String[] args) { try { // 下载或准备库文件 String libDir = "lib"; MarkmapLibraryManager.downloadMarkmapLibraries(libDir); // 读取库文件内容 String d3Content = Files.readString(Paths.get(libDir, "d3.min.js")); String markmapContent = Files.readString(Paths.get(libDir, "markmap.min.js")); // Markdown 内容 String markdown = "# Java Programming\n" + "## Core Concepts\n" + "- Data Types\n" + "- Control Structures\n" + "## Advanced Topics\n" + "- Concurrency\n" + "- Memory Management"; // 生成 HTML String html = generateMarkmapHtml(markdown, d3Content, markmapContent); Files.write(Paths.get("mindmap.html"), html.getBytes()); System.out.println("Markmap HTML generated successfully!"); } catch (Exception e) { e.printStackTrace(); } } } ``` ## 在 Spring Boot 应用中的集成 ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import java.nio.file.Files; import java.nio.file.Paths; @SpringBootApplication public class MarkmapApp { public static void main(String[] args) { SpringApplication.run(MarkmapApp.class, args); } } @Controller class MarkmapController { @GetMapping("/mindmap") public String getMindmap(Model model) throws Exception { // 读取库文件内容 String d3Content = Files.readString(Paths.get("lib/d3.min.js")); String markmapContent = Files.readString(Paths.get("lib/markmap.min.js")); // Markdown 内容(实际中可从数据库获取) String markdown = "# Spring Boot Mindmap\n" + "## Core Modules\n" + "- Spring Boot Starter\n" + "- Auto Configuration\n" + "## Advanced Features\n" + "- Actuator Endpoints\n" + "- Security Integration"; model.addAttribute("d3Js", d3Content); model.addAttribute("markmapJs", markmapContent); model.addAttribute("markdownData", markdown); return "mindmap-view"; } } ``` ```html <!-- src/main/resources/templates/mindmap-view.html --> <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Spring Boot Mindmap</title> <style> /* 样式同上 */ </style> <script th:inline="javascript"> // Inlined d3.js library /*<![CDATA[*/ [[${d3Js}]] /*]]>*/ </script> <script th:inline="javascript"> // Inlined markmap-view library /*<![CDATA[*/ [[${markmapJs}]] /*]]>*/ </script> </head> <body> <div id="container"> <div id="toolbar"> <h2>Spring Boot Mindmap</h2> <div> <button class="btn" id="zoom-in">Zoom In</button> <button class="btn" id="zoom-out">Zoom Out</button> <button class="btn" id="reset">Reset View</button> </div> </div> <div id="mindmap"></div> </div> <script th:inline="javascript"> // Markdown data from Spring Boot const markdownData = /*[[${markdownData}]]*/ ''; // 初始化代码同上... </script> </body> </html> ``` ## 关键点解释 1. **库文件处理**: - 下载预编译的 markmap-view 和 d3.js - 将库文件内联到 HTML 中,避免外部依赖 2. **Markdown 处理**: - 在客户端使用 markmap.transform.parse() 将 Markdown 转换为思维导图数据 - 也可以选择在服务器端转换(需要实现 Markdown 解析器) 3. **交互功能**: - 添加了缩放控制按钮 - 实现了节点点击事件处理 - 响应式布局适配窗口大小变化 4. **样式自定义**: - 自定义节点颜色 - 调整间距和尺寸 - 添加工具栏和标题 ## 备选方案:服务器端渲染 如果您需要在服务器端生成思维导图图片,可以使用无头浏览器方案: ```java import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; public class MarkmapScreenshotter { public static byte[] generateMindmapScreenshot(String markdown) throws Exception { // 生成临时 HTML 文件 String html = MarkmapGenerator.generateMarkmapHtml(markdown, "", ""); Path tempHtml = Files.createTempFile("mindmap", ".html"); Files.write(tempHtml, html.getBytes()); // 配置无头 Chrome ChromeOptions options = new ChromeOptions(); options.addArguments("--headless"); options.addArguments("--disable-gpu"); options.addArguments("--window-size=1200,800"); WebDriver driver = new ChromeDriver(options); try { // 加载 HTML driver.get("file://" + tempHtml.toAbsolutePath()); // 等待渲染完成 Thread.sleep(2000); // 截取整个思维导图 return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES); } finally { driver.quit(); Files.delete(tempHtml); } } public static void main(String[] args) throws Exception { String markdown = "# Server-Side Rendered Mindmap\n- Node 1\n- Node 2"; byte[] screenshot = generateMindmapScreenshot(markdown); Files.write(Paths.get("mindmap.png"), screenshot); System.out.println("Mindmap screenshot generated!"); } } ``` ## 最佳实践建议 1. **库文件管理**: - 将库文件打包在应用中(resources 目录) - 定期更新库文件版本 - 添加完整性校验 2. **性能优化**: - 对大型思维导图使用虚拟滚动 - 实现增量加载 - 添加加载指示器 3. **安全考虑**: - 对用户输入的 Markdown 进行消毒处理 - 限制最大节点数量 - 防止 XSS 攻击 4. **扩展功能**: - 添加节点编辑功能 - 实现导入/导出 - 添加协作功能
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值