Mermaid流程图更改样式的方法

现在很多像deepseek给出的流程图都是用mermaid代码生成的,但是可能这个主题样式不是我们需要的。

复制代码
flowchart TD
    A[第一步] --> B{第二步};
    B -- 批准 --> C[第三步];
    B -- 驳回 --> D[第四步];

批准 驳回 第一步 第二步 第三步 第四步

比如打印的时候需要显示字体为黑色,背景为白色的样式。其实只用再改下配置就行了。

--- config: theme: 'base' themeVariables: primaryColor: '#fff' primaryTextColor: '#000' primaryBorderColor: '#000' lineColor: '#000' secondaryColor: '#fff' tertiaryColor: '#fff' --- flowchart TD A[第一步] --> B{第二步}; B -- 批准 --> C[第三步]; B -- 驳回 --> D[第四步];

下面给个HTML的转换工具,自己把代码复制一下,创建个html文件,把mermaid的代码复制进去就可以转换成功了。

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Mermaid流程图字体调整工具 - 修复版</title>
    <script src="https://unpkg.com/mermaid@11.9.0/dist/mermaid.min.js"></script>
	
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 20px;
            color: #333;
        }
        
        .container {
            max-width: 1200px;
            width: 100%;
            background: white;
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
            overflow: hidden;
            margin: 20px 0;
        }
        
        header {
            background: #4a6bdf;
            color: white;
            padding: 25px;
            text-align: center;
        }
        
        h1 {
            font-size: 2.2rem;
            margin-bottom: 10px;
        }
        
        .subtitle {
            font-size: 1.1rem;
            opacity: 0.9;
        }
        
        .main-content {
            display: flex;
            flex-wrap: wrap;
            padding: 20px;
        }
        
        .input-section, .preview-section {
            flex: 1;
            min-width: 300px;
            padding: 20px;
        }
        
        .section-title {
            font-size: 1.3rem;
            margin-bottom: 15px;
            color: #4a6bdf;
            border-bottom: 2px solid #e0e0e0;
            padding-bottom: 8px;
        }
        
        .mermaid-input {
            width: 100%;
            height: 300px;
            padding: 15px;
            border: 2px dashed #4a6bdf;
            border-radius: 8px;
            font-family: monospace;
            resize: vertical;
            margin-bottom: 15px;
            font-size: 14px;
            line-height: 1.5;
        }
        
        .preview-area {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            border: 2px dashed #4a6bdf;
            border-radius: 8px;
            min-height: 400px;
            padding: 20px;
            background: #f9f9f9;
            overflow: auto;
        }
        
        #mermaid-preview {
            width: 100%;
            display: flex;
            justify-content: center;
            overflow: auto;
        }
        
        #png-preview {
            display: none;
            max-width: 100%;
        }
        
        .controls {
            display: flex;
            justify-content: center;
            gap: 15px;
            margin: 20px 0;
            flex-wrap: wrap;
        }
        
        .btn {
            padding: 12px 25px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 1rem;
            transition: all 0.3s;
            font-weight: 600;
        }
        
        .render-btn {
            background: #4a6bdf;
            color: white;
        }
        
        .render-btn:hover {
            background: #3a5bc7;
        }
        
        .convert-btn {
            background: #4caf50;
            color: white;
        }
        
        .convert-btn:hover {
            background: #3d8b40;
        }
        
        .download-btn {
            background: #ff9800;
            color: white;
        }
        
        .download-btn:hover {
            background: #e68900;
        }
        
        .download-btn:disabled {
            background: #cccccc;
            cursor: not-allowed;
        }
        
        .message {
            text-align: center;
            margin: 10px 0;
            padding: 10px;
            border-radius: 5px;
        }
        
        .error {
            background: #ffebee;
            color: #d32f2f;
        }
        
        .success {
            background: #e8f5e9;
            color: #2e7d32;
        }
        
        .instructions {
            background: #e3f2fd;
            padding: 20px;
            border-radius: 8px;
            margin-top: 20px;
        }
        
        .instructions h3 {
            color: #4a6bdf;
            margin-bottom: 10px;
        }
        
        .instructions ul {
            padding-left: 20px;
            margin: 10px 0;
        }
        
        .instructions li {
            margin-bottom: 8px;
        }
        
        footer {
            text-align: center;
            padding: 20px;
            color: #666;
            font-size: 0.9rem;
        }
        
        @media (max-width: 768px) {
            .main-content {
                flex-direction: column;
            }
        }
        
        .loading {
            display: none;
            text-align: center;
            margin: 10px 0;
        }
        
        .loading-spinner {
            border: 4px solid #f3f3f3;
            border-top: 4px solid #4a6bdf;
            border-radius: 50%;
            width: 30px;
            height: 30px;
            animation: spin 1s linear infinite;
            margin: 0 auto;
        }
        
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        
        .font-controls {
            background: #f5f5f5;
            padding: 15px;
            border-radius: 8px;
            margin: 15px 0;
        }
        
        .control-group {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
        }
        
        .control-group label {
            width: 120px;
            font-weight: 500;
        }
        
        .control-group input[type="range"] {
            flex: 1;
            margin: 0 15px;
        }
        
        .control-group span {
            width: 50px;
            text-align: center;
            font-weight: bold;
        }
        
        .checkbox-group {
            display: flex;
            align-items: center;
            margin-top: 15px;
        }
        
        .checkbox-group input {
            margin-right: 10px;
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>Mermaid流程图字体调整工具 - 修复版</h1>
            <p class="subtitle">修复字体调整问题,确保PNG输出正确显示</p>
        </header>
        
        <div class="main-content">
            <div class="input-section">
                <h2 class="section-title">Mermaid代码</h2>
                <textarea class="mermaid-input" id="mermaid-code" placeholder="在此输入Mermaid代码..."></textarea>
                
                <div class="font-controls">
                    <h3>字体设置</h3>
                    <div class="control-group">
                        <label for="font-size">字体大小:</label>
                        <input type="range" id="font-size" min="12" max="24" value="16" step="1">
                        <span id="font-size-value">16px</span>
                    </div>
                    
                    <div class="control-group">
                        <label for="font-weight">字体粗细:</label>
                        <input type="range" id="font-weight" min="300" max="900" value="600" step="100">
                        <span id="font-weight-value">600</span>
                    </div>
                    
                    <div class="checkbox-group">
                        <input type="checkbox" id="bold-titles" checked>
                        <label for="bold-titles">节点标题加粗</label>
                    </div>
                </div>
                
                <div class="controls">
                    <button class="btn render-btn" id="render-btn">应用字体设置并渲染</button>
                </div>
            </div>
            
            <div class="preview-section">
                <h2 class="section-title">预览</h2>
                <div class="preview-area">
                    <div id="mermaid-preview">
                        <p>流程图将在此处渲染</p>
                    </div>
                    <img id="png-preview" alt="PNG预览">
                </div>
                
                <div class="loading">
                    <div class="loading-spinner"></div>
                    <p>正在转换中,请稍候...</p>
                </div>
                
                <div class="controls">
                    <button class="btn convert-btn" id="convert-btn" disabled>转换为PNG</button>
                    <button class="btn download-btn" id="download-btn" disabled>下载PNG</button>
                </div>
                
                <div id="message" class="message"></div>
            </div>
        </div>
        
        <div class="instructions">
            <h3>使用说明</h3>
            <ul>
                <li>在左侧文本框中输入或粘贴Mermaid流程图代码</li>
                <li>使用滑块调整字体大小和粗细</li>
                <li>点击"应用字体设置并渲染"按钮预览流程图</li>
                <li>点击"转换为PNG"按钮生成PNG图像</li>
                <li>转换完成后,点击"下载PNG"按钮保存PNG图像到本地</li>
            </ul>
        </div>
    </div>
    
    <footer>
        <p>© 2025 Mermaid流程图字体调整工具 | 修复字体调整问题</p>
    </footer>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            // 初始化Mermaid
            mermaid.initialize({
                startOnLoad: false,
                theme: 'default',
                flowchart: {
                    useMaxWidth: false,
                    htmlLabels: true,
                    curve: 'basis'
                }
            });
			
            
            const mermaidCode = document.getElementById('mermaid-code');
            const fontSizeSlider = document.getElementById('font-size');
            const fontSizeValue = document.getElementById('font-size-value');
            const fontWeightSlider = document.getElementById('font-weight');
            const fontWeightValue = document.getElementById('font-weight-value');
            const boldTitles = document.getElementById('bold-titles');
            const renderBtn = document.getElementById('render-btn');
            const convertBtn = document.getElementById('convert-btn');
            const downloadBtn = document.getElementById('download-btn');
            const mermaidPreview = document.getElementById('mermaid-preview');
            const pngPreview = document.getElementById('png-preview');
            const messageEl = document.getElementById('message');
            const loadingEl = document.querySelector('.loading');
            
            let svgElement = null;
            let pngDataUrl = null;
            
            // 更新滑块值显示
            fontSizeSlider.addEventListener('input', function() {
                fontSizeValue.textContent = this.value + 'px';
            });
            
            fontWeightSlider.addEventListener('input', function() {
                fontWeightValue.textContent = this.value;
            });
            
            // 渲染Mermaid图表
            renderBtn.addEventListener('click', function() {
                try {
                    clearMessage();
                    mermaidPreview.innerHTML = '<p>正在渲染...</p>';
                    
                    const code = mermaidCode.value;
                    if (!code.trim()) {
                        showMessage('请输入Mermaid代码', 'error');
                        return;
                    }
                    
                    // 使用Mermaid渲染
                    mermaid.render('mermaid-chart', code).then(function(result) {
                        mermaidPreview.innerHTML = result.svg;
                        svgElement = mermaidPreview.querySelector('svg');
                        
                        // 应用字体设置
                        applyFontStyles();
                        
                        // 启用转换按钮
                        convertBtn.disabled = false;
                        showMessage('流程图渲染成功!现在可以转换为PNG。', 'success');
                    }).catch(function(error) {
                        showMessage('Mermaid代码错误: ' + error.message, 'error');
                        console.error('Mermaid渲染错误:', error);
                    });
                } catch (error) {
                    showMessage('渲染过程中出错: ' + error.message, 'error');
                    console.error('渲染错误:', error);
                }
            });
            
            // 应用字体样式到SVG - 修复版本
            function applyFontStyles() {
                if (!svgElement) return;
                
                const fontSize = fontSizeSlider.value;
                const fontWeight = fontWeightSlider.value;
                
                // 获取所有文本元素
                const textElements = svgElement.querySelectorAll('text, tspan');
                
                textElements.forEach(text => {
                    // 使用setAttribute设置字体大小和粗细
                    text.setAttribute('font-size', fontSize);
                    text.setAttribute('font-weight', fontWeight);
                    
                    // 如果是节点标题且需要加粗,则再加粗一次
                    if (boldTitles.checked) {
                        const parent = text.parentElement;
                        if (parent && (parent.classList.contains('node') || 
                                       parent.classList.contains('cluster') ||
                                       parent.querySelector('rect'))) {
                            text.setAttribute('font-weight', 'bold');
                        }
                    }
                });
                
                // 调整SVG大小以适应更大的字体
                const bbox = svgElement.getBBox();
                svgElement.setAttribute('width', bbox.width + 100);
                svgElement.setAttribute('height', bbox.height + 100);
                svgElement.setAttribute('viewBox', `${bbox.x - 50} ${bbox.y - 50} ${bbox.width + 100} ${bbox.height + 100}`);
            }
            
            // 转换为PNG
            convertBtn.addEventListener('click', function() {
                if (!svgElement) {
                    showMessage('请先渲染流程图', 'error');
                    return;
                }
                
                try {
                    loadingEl.style.display = 'block';
                    clearMessage();
                    
                    // 创建SVG的副本,避免影响预览
                    const svgClone = svgElement.cloneNode(true);
                    
                    // 确保所有字体样式都应用到了克隆的SVG上
                    const fontSize = fontSizeSlider.value;
                    const fontWeight = fontWeightSlider.value;
                    const textElements = svgClone.querySelectorAll('text, tspan');
                    
                    textElements.forEach(text => {
                        text.setAttribute('font-size', fontSize);
                        text.setAttribute('font-weight', fontWeight);
                        
                        if (boldTitles.checked) {
                            const parent = text.parentElement;
                            if (parent && (parent.classList.contains('node') || 
                                           parent.classList.contains('cluster') ||
                                           parent.querySelector('rect'))) {
                                text.setAttribute('font-weight', 'bold');
                            }
                        }
                    });
                    
                    // 获取SVG字符串
                    const svgString = new XMLSerializer().serializeToString(svgClone);
                    
                    // 使用SVG数据URL而不是Blob URL,避免跨域问题
                    const svgData = encodeURIComponent(svgString);
                    const dataUrl = 'data:image/svg+xml;charset=utf-8,' + svgData;
                    
                    // 创建Image对象
                    const img = new Image();
                    
                    // 设置crossOrigin属性为anonymous,防止跨域问题
                    img.crossOrigin = 'anonymous';
                    
                    img.onload = function() {
                        // 创建Canvas
                        const canvas = document.createElement('canvas');
                        const scale = 2; // 提高分辨率
                        canvas.width = img.width * scale;
                        canvas.height = img.height * scale;
                        
                        // 绘制图像到Canvas
                        const ctx = canvas.getContext('2d');
                        ctx.scale(scale, scale);
                        
                        // 填充白色背景(解决透明背景问题)
                        ctx.fillStyle = 'white';
                        ctx.fillRect(0, 0, canvas.width, canvas.height);
                        
                        ctx.drawImage(img, 0, 0);
                        
                        try {
                            // 获取PNG数据URL
                            pngDataUrl = canvas.toDataURL('image/png');
                            
                            // 显示PNG预览
                            pngPreview.src = pngDataUrl;
                            pngPreview.style.display = 'block';
                            mermaidPreview.style.display = 'none';
                            
                            // 启用下载按钮
                            downloadBtn.disabled = false;
                            
                            showMessage('转换成功!现在可以下载PNG图像了。', 'success');
                        } catch (e) {
                            showMessage('PNG转换失败: ' + e.message, 'error');
                            console.error('PNG转换错误:', e);
                        }
                        
                        loadingEl.style.display = 'none';
                    };
                    
                    img.onerror = function() {
                        showMessage('SVG加载失败', 'error');
                        loadingEl.style.display = 'none';
                    };
                    
                    img.src = dataUrl;
                } catch (error) {
                    showMessage('转换过程中出错: ' + error.message, 'error');
                    loadingEl.style.display = 'none';
                    console.error('转换错误:', error);
                }
            });
            
            // 下载PNG
            downloadBtn.addEventListener('click', function() {
                if (pngDataUrl) {
                    const a = document.createElement('a');
                    a.href = pngDataUrl;
                    a.download = 'mermaid-flowchart.png';
                    document.body.appendChild(a);
                    a.click();
                    document.body.removeChild(a);
                }
            });
            
            // 显示消息
            function showMessage(text, type) {
                messageEl.textContent = text;
                messageEl.className = `message ${type}`;
            }
            
            // 清除消息
            function clearMessage() {
                messageEl.textContent = '';
                messageEl.className = 'message';
            }
            
            // 初始渲染
            renderBtn.click();
        });
    </script>
</body>
</html>

官方文档地址:https://mermaid.nodejs.cn/

相关推荐
disgare5 小时前
如何画时序图、流程图
流程图
芦苇Z6 小时前
CSS :has() 父级选择器与关系查询
前端·css
低代码布道师6 小时前
CSS 伪类与伪元素:深度解析
前端·css
星月前端6 小时前
css3元素倒影效果属性:box-reflect
前端·css·css3
@HNUSTer7 小时前
基于 HTML、CSS 和 JavaScript 的智能图像灰度直方图分析系统
开发语言·前端·javascript·css·html
0x0007 小时前
CSS - 子元素 hover 鼠标悬浮时避免触发父元素的 hover 效果
css
dreams_dream14 小时前
vue2滑块验证
前端·javascript·css
ᥬ 小月亮21 小时前
uniapp中输入金额的过滤(只允许输入数字和小数点)
前端·css·uni-app
前端老鹰1 天前
HTML `<datalist>`:原生下拉搜索框,无需 JS 也能实现联想功能
前端·css·html