feat: 添加 Mermaid 图表缩放功能
- 图表容器宽度占满,只留文章边距(margin: 20px -20px) - 添加缩放控制按钮:放大、缩小、重置 - 支持 Ctrl+滚轮缩放 - 缩放范围:50%-300%,步进 25% - 响应式适配:移动端自动调整边距和按钮大小 - 夜间模式适配缩放控制按钮样式
This commit is contained in:
@@ -5147,7 +5147,7 @@ void 0;
|
||||
// ---------- 样式增强 ----------
|
||||
|
||||
/**
|
||||
* 应用容器样式
|
||||
* 应用容器样式并添加缩放控制
|
||||
* @param {HTMLElement} container - 图表容器
|
||||
*/
|
||||
applyStyles(container) {
|
||||
@@ -5161,9 +5161,88 @@ void 0;
|
||||
// 确保 SVG 响应式
|
||||
const svg = container.querySelector('svg');
|
||||
if (svg) {
|
||||
svg.style.maxWidth = '100%';
|
||||
svg.style.width = '100%';
|
||||
svg.style.height = 'auto';
|
||||
}
|
||||
|
||||
// 添加缩放功能
|
||||
this.addZoomControls(container);
|
||||
},
|
||||
|
||||
/**
|
||||
* 添加缩放控制按钮
|
||||
* @param {HTMLElement} container - 图表容器
|
||||
*/
|
||||
addZoomControls(container) {
|
||||
// 创建内部容器包裹 SVG
|
||||
const svg = container.querySelector('svg');
|
||||
if (!svg) return;
|
||||
|
||||
// 创建内部容器
|
||||
const inner = document.createElement('div');
|
||||
inner.className = 'mermaid-container-inner';
|
||||
|
||||
// 将 SVG 移到内部容器
|
||||
container.appendChild(inner);
|
||||
inner.appendChild(svg);
|
||||
|
||||
// 创建缩放控制
|
||||
const controls = document.createElement('div');
|
||||
controls.className = 'mermaid-zoom-controls';
|
||||
controls.innerHTML = `
|
||||
<button class="mermaid-zoom-btn" data-action="zoom-out" title="缩小">−</button>
|
||||
<span class="mermaid-zoom-level">100%</span>
|
||||
<button class="mermaid-zoom-btn" data-action="zoom-in" title="放大">+</button>
|
||||
<button class="mermaid-zoom-btn" data-action="zoom-reset" title="重置">⟲</button>
|
||||
`;
|
||||
|
||||
container.appendChild(controls);
|
||||
|
||||
// 缩放状态
|
||||
let scale = 1;
|
||||
const minScale = 0.5;
|
||||
const maxScale = 3;
|
||||
const step = 0.25;
|
||||
|
||||
// 更新缩放显示
|
||||
const updateZoom = () => {
|
||||
inner.style.transform = `scale(${scale})`;
|
||||
controls.querySelector('.mermaid-zoom-level').textContent = Math.round(scale * 100) + '%';
|
||||
};
|
||||
|
||||
// 绑定按钮事件
|
||||
controls.addEventListener('click', (e) => {
|
||||
const btn = e.target.closest('.mermaid-zoom-btn');
|
||||
if (!btn) return;
|
||||
|
||||
const action = btn.dataset.action;
|
||||
|
||||
if (action === 'zoom-in' && scale < maxScale) {
|
||||
scale = Math.min(scale + step, maxScale);
|
||||
updateZoom();
|
||||
} else if (action === 'zoom-out' && scale > minScale) {
|
||||
scale = Math.max(scale - step, minScale);
|
||||
updateZoom();
|
||||
} else if (action === 'zoom-reset') {
|
||||
scale = 1;
|
||||
updateZoom();
|
||||
}
|
||||
});
|
||||
|
||||
// 鼠标滚轮缩放(按住 Ctrl)
|
||||
container.addEventListener('wheel', (e) => {
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
e.preventDefault();
|
||||
|
||||
const delta = e.deltaY > 0 ? -step : step;
|
||||
const newScale = Math.max(minScale, Math.min(maxScale, scale + delta));
|
||||
|
||||
if (newScale !== scale) {
|
||||
scale = newScale;
|
||||
updateZoom();
|
||||
}
|
||||
}
|
||||
}, { passive: false });
|
||||
},
|
||||
|
||||
// ---------- 主题切换监听 ----------
|
||||
|
||||
202
style.css
202
style.css
@@ -913,21 +913,81 @@ article .wp-block-separator {
|
||||
background: var(--color-foreground);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
margin: 20px -20px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
overflow-x: auto;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
opacity: 0;
|
||||
animation: mermaidFadeIn 0.3s ease-in-out forwards;
|
||||
}
|
||||
|
||||
.mermaid-container-inner {
|
||||
overflow: auto;
|
||||
transform-origin: top left;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.mermaid-container svg {
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 缩放控制按钮 */
|
||||
.mermaid-zoom-controls {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
z-index: 10;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border-radius: 6px;
|
||||
padding: 5px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
html.darkmode .mermaid-zoom-controls {
|
||||
background: rgba(30, 30, 30, 0.9);
|
||||
}
|
||||
|
||||
.mermaid-zoom-btn {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 18px;
|
||||
color: #5e72e4;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.mermaid-zoom-btn:hover {
|
||||
background: rgba(94, 114, 228, 0.1);
|
||||
}
|
||||
|
||||
.mermaid-zoom-btn:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.mermaid-zoom-level {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 8px;
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
min-width: 50px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
html.darkmode .mermaid-zoom-level {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
/* Mermaid 淡入动画 */
|
||||
@keyframes mermaidFadeIn {
|
||||
from {
|
||||
@@ -942,7 +1002,42 @@ article .wp-block-separator {
|
||||
|
||||
/* 文章卡片内的 Mermaid 图表 */
|
||||
article.card .mermaid-container {
|
||||
margin: 20px 0;
|
||||
margin: 20px -20px;
|
||||
}
|
||||
|
||||
/* 响应式调整 */
|
||||
@media screen and (max-width: 768px) {
|
||||
.mermaid-container {
|
||||
margin: 15px -15px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
article.card .mermaid-container {
|
||||
margin: 15px -15px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
.mermaid-container {
|
||||
margin: 10px -10px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
article.card .mermaid-container {
|
||||
margin: 10px -10px;
|
||||
}
|
||||
|
||||
.mermaid-zoom-controls {
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.mermaid-zoom-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mermaid 错误提示样式 */
|
||||
@@ -16629,24 +16724,85 @@ html.darkmode .mermaid-error-container .error-code code {
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
overflow-x: auto;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
margin: 20px -20px;
|
||||
transition: opacity 0.3s ease-in;
|
||||
}
|
||||
|
||||
.mermaid-container-inner {
|
||||
overflow: auto;
|
||||
transform-origin: top left;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.mermaid-container svg {
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 缩放控制按钮 */
|
||||
.mermaid-zoom-controls {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
z-index: 10;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border-radius: 6px;
|
||||
padding: 5px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
html.darkmode .mermaid-zoom-controls {
|
||||
background: rgba(30, 30, 30, 0.9);
|
||||
}
|
||||
|
||||
.mermaid-zoom-btn {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 18px;
|
||||
color: #5e72e4;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.mermaid-zoom-btn:hover {
|
||||
background: rgba(94, 114, 228, 0.1);
|
||||
}
|
||||
|
||||
.mermaid-zoom-btn:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.mermaid-zoom-level {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 8px;
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
min-width: 50px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
html.darkmode .mermaid-zoom-level {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
/* ---------- 卡片内的 Mermaid 图表 ---------- */
|
||||
.card .mermaid-container,
|
||||
.post-card .mermaid-container,
|
||||
.comment-content .mermaid-container {
|
||||
padding: 15px;
|
||||
margin: 15px 0;
|
||||
margin: 15px -15px;
|
||||
}
|
||||
|
||||
/* ---------- 夜间模式适配 ---------- */
|
||||
@@ -16659,15 +16815,39 @@ html.darkmode .mermaid-container {
|
||||
@media screen and (max-width: 768px) {
|
||||
.mermaid-container {
|
||||
padding: 15px;
|
||||
margin: 15px 0;
|
||||
margin: 15px -15px;
|
||||
border-radius: calc(var(--card-radius) * 0.8);
|
||||
}
|
||||
|
||||
.card .mermaid-container,
|
||||
.post-card .mermaid-container,
|
||||
.comment-content .mermaid-container {
|
||||
margin: 15px -15px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
.mermaid-container {
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
margin: 10px -10px;
|
||||
}
|
||||
|
||||
.card .mermaid-container,
|
||||
.post-card .mermaid-container,
|
||||
.comment-content .mermaid-container {
|
||||
margin: 10px -10px;
|
||||
}
|
||||
|
||||
.mermaid-zoom-controls {
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.mermaid-zoom-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user