feat: 添加 Mermaid 图表缩放功能
- 图表容器宽度占满,只留文章边距(margin: 20px -20px) - 添加缩放控制按钮:放大、缩小、重置 - 支持 Ctrl+滚轮缩放 - 缩放范围:50%-300%,步进 25% - 响应式适配:移动端自动调整边距和按钮大小 - 夜间模式适配缩放控制按钮样式
This commit is contained in:
@@ -5147,7 +5147,7 @@ void 0;
|
|||||||
// ---------- 样式增强 ----------
|
// ---------- 样式增强 ----------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用容器样式
|
* 应用容器样式并添加缩放控制
|
||||||
* @param {HTMLElement} container - 图表容器
|
* @param {HTMLElement} container - 图表容器
|
||||||
*/
|
*/
|
||||||
applyStyles(container) {
|
applyStyles(container) {
|
||||||
@@ -5161,9 +5161,88 @@ void 0;
|
|||||||
// 确保 SVG 响应式
|
// 确保 SVG 响应式
|
||||||
const svg = container.querySelector('svg');
|
const svg = container.querySelector('svg');
|
||||||
if (svg) {
|
if (svg) {
|
||||||
svg.style.maxWidth = '100%';
|
svg.style.width = '100%';
|
||||||
svg.style.height = 'auto';
|
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);
|
background: var(--color-foreground);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
margin: 20px 0;
|
margin: 20px -20px;
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
overflow-x: auto;
|
overflow: hidden;
|
||||||
max-width: 100%;
|
position: relative;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
animation: mermaidFadeIn 0.3s ease-in-out forwards;
|
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 {
|
.mermaid-container svg {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
height: auto !important;
|
height: auto !important;
|
||||||
max-width: 100%;
|
|
||||||
display: block;
|
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 淡入动画 */
|
/* Mermaid 淡入动画 */
|
||||||
@keyframes mermaidFadeIn {
|
@keyframes mermaidFadeIn {
|
||||||
from {
|
from {
|
||||||
@@ -942,7 +1002,42 @@ article .wp-block-separator {
|
|||||||
|
|
||||||
/* 文章卡片内的 Mermaid 图表 */
|
/* 文章卡片内的 Mermaid 图表 */
|
||||||
article.card .mermaid-container {
|
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 错误提示样式 */
|
/* Mermaid 错误提示样式 */
|
||||||
@@ -16629,24 +16724,85 @@ html.darkmode .mermaid-error-container .error-code code {
|
|||||||
padding: 20px;
|
padding: 20px;
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
overflow-x: auto;
|
overflow: hidden;
|
||||||
max-width: 100%;
|
position: relative;
|
||||||
|
margin: 20px -20px;
|
||||||
transition: opacity 0.3s ease-in;
|
transition: opacity 0.3s ease-in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mermaid-container-inner {
|
||||||
|
overflow: auto;
|
||||||
|
transform-origin: top left;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
.mermaid-container svg {
|
.mermaid-container svg {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
height: auto !important;
|
height: auto !important;
|
||||||
max-width: 100%;
|
|
||||||
display: block;
|
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 图表 ---------- */
|
/* ---------- 卡片内的 Mermaid 图表 ---------- */
|
||||||
.card .mermaid-container,
|
.card .mermaid-container,
|
||||||
.post-card .mermaid-container,
|
.post-card .mermaid-container,
|
||||||
.comment-content .mermaid-container {
|
.comment-content .mermaid-container {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
margin: 15px 0;
|
margin: 15px -15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- 夜间模式适配 ---------- */
|
/* ---------- 夜间模式适配 ---------- */
|
||||||
@@ -16659,15 +16815,39 @@ html.darkmode .mermaid-container {
|
|||||||
@media screen and (max-width: 768px) {
|
@media screen and (max-width: 768px) {
|
||||||
.mermaid-container {
|
.mermaid-container {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
margin: 15px 0;
|
margin: 15px -15px;
|
||||||
border-radius: calc(var(--card-radius) * 0.8);
|
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) {
|
@media screen and (max-width: 480px) {
|
||||||
.mermaid-container {
|
.mermaid-container {
|
||||||
padding: 10px;
|
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