feat: 实现 Mermaid 主题自动同步功能

- 在 setDarkmode() 中触发 argon:theme-switched 事件
- 优化 reRenderCharts() 函数,保持图表缩放级别和滚动位置
- 添加淡入淡出过渡动画,提升视觉体验
- 只替换 SVG 内容,保留容器结构和控制按钮
- 主题切换失败时保持原样,不影响用户体验

需求:17.1, 17.2, 17.3, 17.4, 17.5
This commit is contained in:
2026-01-25 01:03:38 +08:00
parent 621341500f
commit 8ba6a15a8a
3 changed files with 126 additions and 23 deletions

View File

@@ -36,10 +36,10 @@
### 阶段 2: Mermaid 显示效果优化
- [~] 5. 优化 Mermaid 工具栏
- [ ] 5.1 实现工具栏自动隐藏 _需求11.1, 11.2_
- [ ] 5.2 优化工具栏样式(半透明背景) _需求11.3-11.5_
- [ ] 5.3 添加按钮提示tooltip _需求20.2_
- [x] 5. 优化 Mermaid 工具栏
- [x] 5.1 实现工具栏自动隐藏 _需求11.1, 11.2_
- [x] 5.2 优化工具栏样式(半透明背景) _需求11.3-11.5_
- [x] 5.3 添加按钮提示tooltip _需求20.2_
- [~] 6. 增强 Mermaid 缩放功能
- [ ] 6.1 实现以鼠标为中心的缩放 _需求12.1_
@@ -72,10 +72,10 @@
### 阶段 4: Mermaid 主题和性能优化
- [~] 11. 优化 Mermaid 主题同步
- [ ] 11.1 实现主题自动切换 _需求17.1, 17.2_
- [ ] 11.2 保持图表状态 _需求17.3_
- [ ] 11.3 添加主题切换动画 _需求17.4, 17.5_
- [x] 11. 优化 Mermaid 主题同步
- [x] 11.1 实现主题自动切换 _需求17.1, 17.2_
- [x] 11.2 保持图表状态 _需求17.3_
- [x] 11.3 添加主题切换动画 _需求17.4, 17.5_
- [~] 12. 优化 Mermaid 渲染性能
- [ ] 12.1 实现批量渲染 _需求18.1_

View File

@@ -5700,6 +5700,8 @@ void 0;
/**
* 重新渲染所有图表(主题切换时)
* 需求 17.3: 保持图表的缩放级别和位置
* 需求 17.4, 17.5: 使用淡入淡出过渡效果
*/
reRenderCharts() {
// 只选择成功渲染的图表容器,排除错误容器
@@ -5748,25 +5750,121 @@ void 0;
return;
}
const chartId = `mermaid-chart-rerender-${Date.now()}-${index}`;
// 需求 17.3: 保存当前的缩放级别和滚动位置
const inner = chart.querySelector('.mermaid-container-inner');
let savedState = null;
window.mermaid.render(`mermaid-svg-${chartId}`, code).then(result => {
chart.innerHTML = result.svg;
chart.dataset.currentTheme = newTheme;
if (inner) {
const transform = window.getComputedStyle(inner).transform;
const scrollLeft = inner.scrollLeft;
const scrollTop = inner.scrollTop;
// 确保 SVG 响应式
const svg = chart.querySelector('svg');
if (svg) {
svg.style.maxWidth = '100%';
svg.style.height = 'auto';
// 提取缩放比例
let scale = 1;
if (transform && transform !== 'none') {
const matrix = transform.match(/matrix\(([^)]+)\)/);
if (matrix) {
const values = matrix[1].split(',').map(v => parseFloat(v.trim()));
scale = values[0]; // scaleX
}
}
this.logDebug(`图表重新渲染成功: ${chartId}`);
}).catch(error => {
this.logError('图表重新渲染失败', error);
// 重新渲染失败时,不替换为错误容器,保持原样
// 因为之前已经成功渲染过,只是主题切换失败
});
savedState = {
scale: scale,
scrollLeft: scrollLeft,
scrollTop: scrollTop
};
this.logDebug('保存图表状态', savedState);
}
const chartId = `mermaid-chart-rerender-${Date.now()}-${index}`;
// 需求 17.4: 添加淡出动画
chart.style.transition = 'opacity 0.2s ease-out';
chart.style.opacity = '0';
// 等待淡出完成后重新渲染
setTimeout(() => {
window.mermaid.render(`mermaid-svg-${chartId}`, code).then(result => {
// 保存旧的内部容器引用
const oldInner = chart.querySelector('.mermaid-container-inner');
// 更新 SVG 内容
if (oldInner) {
// 只替换 SVG保留容器结构
const oldSvg = oldInner.querySelector('svg');
if (oldSvg) {
// 创建临时容器解析新的 SVG
const temp = document.createElement('div');
temp.innerHTML = result.svg;
const newSvg = temp.querySelector('svg');
if (newSvg) {
// 替换 SVG
oldSvg.replaceWith(newSvg);
// 确保 SVG 响应式
newSvg.style.width = '100%';
newSvg.style.height = 'auto';
}
}
} else {
// 如果没有内部容器,直接替换内容
chart.innerHTML = result.svg;
// 确保 SVG 响应式
const svg = chart.querySelector('svg');
if (svg) {
svg.style.width = '100%';
svg.style.height = 'auto';
}
}
// 更新主题标记
chart.dataset.currentTheme = newTheme;
// 需求 17.3: 恢复缩放级别和滚动位置
if (savedState && oldInner) {
// 恢复缩放
oldInner.style.transform = `scale(${savedState.scale})`;
// 恢复滚动位置
oldInner.scrollLeft = savedState.scrollLeft;
oldInner.scrollTop = savedState.scrollTop;
// 更新缩放显示
const zoomLevel = chart.querySelector('.mermaid-zoom-level');
if (zoomLevel) {
zoomLevel.textContent = Math.round(savedState.scale * 100) + '%';
}
this.logDebug('恢复图表状态', savedState);
}
// 需求 17.5: 添加淡入动画
requestAnimationFrame(() => {
chart.style.transition = 'opacity 0.3s ease-in';
chart.style.opacity = '1';
// 动画完成后清理过渡样式
setTimeout(() => {
chart.style.transition = '';
}, 300);
});
this.logDebug(`图表重新渲染成功: ${chartId}`);
}).catch(error => {
this.logError('图表重新渲染失败', error);
// 重新渲染失败时,恢复显示
chart.style.opacity = '1';
chart.style.transition = '';
// 不替换为错误容器,保持原样
// 因为之前已经成功渲染过,只是主题切换失败
});
}, 200); // 等待淡出动画完成
});
} catch (error) {

View File

@@ -528,6 +528,11 @@
}
// 触发主题切换事件(用于 Mermaid 等组件响应主题变化)
document.dispatchEvent(new CustomEvent('argon:theme-switched', {
detail: { darkmode: enable }
}));
}
function toggleDarkmode(){