现在很多像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的代码复制进去就可以转换成功了。
<!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/