342 lines
14 KiB
HTML
342 lines
14 KiB
HTML
|
|
<!DOCTYPE html>
|
|||
|
|
<html lang="zh-CN">
|
|||
|
|
|
|||
|
|
<head>
|
|||
|
|
<meta charset="UTF-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
|
<title>信息图样式调试</title>
|
|||
|
|
<script src="https://registry.npmmirror.com/@antv/infographic/0.2.1/files/dist/infographic.min.js"></script>
|
|||
|
|
<style>
|
|||
|
|
* {
|
|||
|
|
box-sizing: border-box;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
body {
|
|||
|
|
margin: 0;
|
|||
|
|
padding: 20px;
|
|||
|
|
background: #f0f0f0;
|
|||
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.debug-container {
|
|||
|
|
display: flex;
|
|||
|
|
gap: 20px;
|
|||
|
|
max-width: 1400px;
|
|||
|
|
margin: 0 auto;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.controls {
|
|||
|
|
width: 300px;
|
|||
|
|
background: white;
|
|||
|
|
padding: 20px;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|||
|
|
height: fit-content;
|
|||
|
|
position: sticky;
|
|||
|
|
top: 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.controls h2 {
|
|||
|
|
margin-top: 0;
|
|||
|
|
font-size: 16px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.controls label {
|
|||
|
|
display: block;
|
|||
|
|
margin: 12px 0 4px;
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #666;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.controls input,
|
|||
|
|
.controls select {
|
|||
|
|
width: 100%;
|
|||
|
|
padding: 8px;
|
|||
|
|
border: 1px solid #ddd;
|
|||
|
|
border-radius: 4px;
|
|||
|
|
font-size: 14px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.controls button {
|
|||
|
|
width: 100%;
|
|||
|
|
padding: 10px;
|
|||
|
|
margin-top: 16px;
|
|||
|
|
background: #6366f1;
|
|||
|
|
color: white;
|
|||
|
|
border: none;
|
|||
|
|
border-radius: 6px;
|
|||
|
|
cursor: pointer;
|
|||
|
|
font-size: 14px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.controls button:hover {
|
|||
|
|
background: #4f46e5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.preview {
|
|||
|
|
flex: 1;
|
|||
|
|
background: white;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#infographic-container {
|
|||
|
|
min-height: 500px;
|
|||
|
|
padding: 24px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* ========== 可调试的样式 ========== */
|
|||
|
|
/* 这些样式可以直接在这里修改,刷新页面即可看到效果 */
|
|||
|
|
|
|||
|
|
/* 基础字体 */
|
|||
|
|
#infographic-container svg text {
|
|||
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#infographic-container svg foreignObject {
|
|||
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif !important;
|
|||
|
|
line-height: 1.4 !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 标题样式 - 根据需要调整 */
|
|||
|
|
#infographic-container svg foreignObject h1,
|
|||
|
|
#infographic-container svg foreignObject [class*="title"] {
|
|||
|
|
font-size: 0.8em !important;
|
|||
|
|
white-space: nowrap !important;
|
|||
|
|
overflow: hidden !important;
|
|||
|
|
text-overflow: ellipsis !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#infographic-container svg foreignObject h2,
|
|||
|
|
#infographic-container svg foreignObject [class*="subtitle"] {
|
|||
|
|
font-size: 0.85em !important;
|
|||
|
|
white-space: nowrap !important;
|
|||
|
|
overflow: hidden !important;
|
|||
|
|
text-overflow: ellipsis !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* ========== 调试样式结束 ========== */
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
|
|||
|
|
<body>
|
|||
|
|
<div class="debug-container">
|
|||
|
|
<div class="controls">
|
|||
|
|
<h2>🔧 样式调试面板</h2>
|
|||
|
|
|
|||
|
|
<label>一级标题字体大小</label>
|
|||
|
|
<input type="text" id="h1-size" value="1.2em" placeholder="例如: 1.2em, 20px">
|
|||
|
|
|
|||
|
|
<label>二级标题字体大小</label>
|
|||
|
|
<input type="text" id="h2-size" value="0.6em" placeholder="例如: 0.6em, 12px">
|
|||
|
|
|
|||
|
|
<label>标题换行设置</label>
|
|||
|
|
<select id="title-wrap">
|
|||
|
|
<option value="nowrap">不换行 (nowrap)</option>
|
|||
|
|
<option value="normal">自动换行 (normal)</option>
|
|||
|
|
</select>
|
|||
|
|
|
|||
|
|
<label>行高</label>
|
|||
|
|
<input type="text" id="line-height" value="1.4" placeholder="例如: 1.4, 1.6">
|
|||
|
|
|
|||
|
|
<button onclick="applyStyles()">应用样式</button>
|
|||
|
|
<button onclick="reRender()" style="background: #10b981; margin-top: 8px;">重新渲染</button>
|
|||
|
|
|
|||
|
|
<hr style="margin: 20px 0; border: none; border-top: 1px solid #eee;">
|
|||
|
|
|
|||
|
|
<label>自定义语法内容</label>
|
|||
|
|
<textarea id="syntax-input" rows="10" style="width: 100%; font-size: 12px; font-family: monospace;">infographic list-grid
|
|||
|
|
data
|
|||
|
|
title 2025职业足球运动员成功要素解析
|
|||
|
|
desc 在高度竞争的现代足球体系下,从天赋到职业的进化路径
|
|||
|
|
items
|
|||
|
|
- label 核心入场券:天赋与身体
|
|||
|
|
desc 速度、爆发力及极佳的球感是底线。基本功必须化为肌肉记忆。
|
|||
|
|
icon mdi/lightning-bolt
|
|||
|
|
- label 决定上限:极度自律
|
|||
|
|
desc 包含严苛的饮食、睡眠管理及强大的抗压心态。
|
|||
|
|
icon mdi/shield-star
|
|||
|
|
- label 现代智慧:球商 (IQ)
|
|||
|
|
desc 复杂的战术理解力与阅读比赛能力。
|
|||
|
|
icon mdi/brain
|
|||
|
|
- label 隐形推手:机遇与平台
|
|||
|
|
desc 专业的青训体系、能发掘你的伯乐。
|
|||
|
|
icon mdi/star-shooting</textarea>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="preview">
|
|||
|
|
<div id="infographic-container"></div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
function applyStyles() {
|
|||
|
|
console.log('[Debug] 应用样式到已渲染的元素...');
|
|||
|
|
|
|||
|
|
const h1Size = document.getElementById('h1-size').value;
|
|||
|
|
const h2Size = document.getElementById('h2-size').value;
|
|||
|
|
const titleWrap = document.getElementById('title-wrap').value;
|
|||
|
|
const lineHeight = document.getElementById('line-height').value;
|
|||
|
|
|
|||
|
|
const container = document.getElementById('infographic-container');
|
|||
|
|
|
|||
|
|
// 直接操作 SVG 内的所有文本元素
|
|||
|
|
const allTexts = container.querySelectorAll('svg text');
|
|||
|
|
allTexts.forEach(text => {
|
|||
|
|
text.style.setProperty('font-size', h1Size, 'important');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 操作 foreignObject 内的所有元素
|
|||
|
|
const foreignObjects = container.querySelectorAll('svg foreignObject');
|
|||
|
|
let mainTitleCount = 0;
|
|||
|
|
let itemLabelCount = 0;
|
|||
|
|
let itemDescCount = 0;
|
|||
|
|
let otherCount = 0;
|
|||
|
|
|
|||
|
|
foreignObjects.forEach(fo => {
|
|||
|
|
// 检查 foreignObject 自身的 data-element-type 属性
|
|||
|
|
const elementType = fo.getAttribute('data-element-type');
|
|||
|
|
|
|||
|
|
// 设置 foreignObject 本身的行高
|
|||
|
|
fo.style.setProperty('line-height', lineHeight, 'important');
|
|||
|
|
|
|||
|
|
// 获取内部的第一个元素(通常是 span)
|
|||
|
|
const firstChild = fo.querySelector(':scope > *');
|
|||
|
|
|
|||
|
|
if (!firstChild) return;
|
|||
|
|
|
|||
|
|
// 根据 foreignObject 的类型设置样式
|
|||
|
|
if (elementType === 'title') {
|
|||
|
|
// 主标题
|
|||
|
|
mainTitleCount++;
|
|||
|
|
firstChild.style.setProperty('font-size', h1Size, 'important');
|
|||
|
|
firstChild.style.setProperty('font-weight', 'bold', 'important');
|
|||
|
|
firstChild.style.setProperty('line-height', lineHeight, 'important');
|
|||
|
|
if (titleWrap === 'nowrap') {
|
|||
|
|
firstChild.style.setProperty('white-space', 'nowrap', 'important');
|
|||
|
|
firstChild.style.setProperty('overflow', 'hidden', 'important');
|
|||
|
|
firstChild.style.setProperty('text-overflow', 'ellipsis', 'important');
|
|||
|
|
} else {
|
|||
|
|
firstChild.style.setProperty('white-space', 'normal', 'important');
|
|||
|
|
firstChild.style.setProperty('overflow', 'visible', 'important');
|
|||
|
|
firstChild.style.setProperty('text-overflow', 'clip', 'important');
|
|||
|
|
}
|
|||
|
|
} else if (elementType === 'desc') {
|
|||
|
|
// 页面副标题(主标题下方的描述)
|
|||
|
|
itemLabelCount++; // 归入副标题计数
|
|||
|
|
firstChild.style.setProperty('font-size', h2Size, 'important');
|
|||
|
|
firstChild.style.setProperty('line-height', lineHeight, 'important');
|
|||
|
|
if (titleWrap === 'nowrap') {
|
|||
|
|
firstChild.style.setProperty('white-space', 'nowrap', 'important');
|
|||
|
|
firstChild.style.setProperty('overflow', 'hidden', 'important');
|
|||
|
|
firstChild.style.setProperty('text-overflow', 'ellipsis', 'important');
|
|||
|
|
} else {
|
|||
|
|
firstChild.style.setProperty('white-space', 'normal', 'important');
|
|||
|
|
firstChild.style.setProperty('overflow', 'visible', 'important');
|
|||
|
|
firstChild.style.setProperty('text-overflow', 'clip', 'important');
|
|||
|
|
}
|
|||
|
|
} else if (elementType === 'item-label') {
|
|||
|
|
// 卡片标题
|
|||
|
|
itemLabelCount++;
|
|||
|
|
firstChild.style.setProperty('font-size', h2Size, 'important');
|
|||
|
|
firstChild.style.setProperty('line-height', lineHeight, 'important');
|
|||
|
|
if (titleWrap === 'nowrap') {
|
|||
|
|
firstChild.style.setProperty('white-space', 'nowrap', 'important');
|
|||
|
|
firstChild.style.setProperty('overflow', 'hidden', 'important');
|
|||
|
|
firstChild.style.setProperty('text-overflow', 'ellipsis', 'important');
|
|||
|
|
} else {
|
|||
|
|
firstChild.style.setProperty('white-space', 'normal', 'important');
|
|||
|
|
firstChild.style.setProperty('overflow', 'visible', 'important');
|
|||
|
|
firstChild.style.setProperty('text-overflow', 'clip', 'important');
|
|||
|
|
}
|
|||
|
|
} else if (elementType === 'item-desc') {
|
|||
|
|
// 卡片描述
|
|||
|
|
itemDescCount++;
|
|||
|
|
firstChild.style.setProperty('line-height', lineHeight, 'important');
|
|||
|
|
firstChild.style.setProperty('white-space', 'normal', 'important');
|
|||
|
|
} else {
|
|||
|
|
// 其他元素
|
|||
|
|
otherCount++;
|
|||
|
|
firstChild.style.setProperty('line-height', lineHeight, 'important');
|
|||
|
|
firstChild.style.setProperty('white-space', 'normal', 'important');
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
console.log('[Debug] foreignObject 处理:', '主标题:', mainTitleCount, '卡片标题:', itemLabelCount, '卡片描述:', itemDescCount, '其他:', otherCount);
|
|||
|
|
|
|||
|
|
console.log('[Debug] 样式已应用到', allTexts.length, '个文本元素和', foreignObjects.length, '个 foreignObject');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function reRender() {
|
|||
|
|
const container = document.getElementById('infographic-container');
|
|||
|
|
container.innerHTML = '';
|
|||
|
|
|
|||
|
|
let syntaxContent = document.getElementById('syntax-input').value.trim();
|
|||
|
|
|
|||
|
|
if (typeof AntVInfographic === 'undefined') {
|
|||
|
|
container.innerHTML = '<div style="color: red; padding: 20px;">⚠️ AntV Infographic 库未加载</div>';
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 应用模板映射(与插件保持一致)
|
|||
|
|
const TEMPLATE_MAPPING = {
|
|||
|
|
'list-grid': 'list-grid-compact-card',
|
|||
|
|
'list-vertical': 'list-column-simple-vertical-arrow',
|
|||
|
|
'tree-vertical': 'hierarchy-tree-tech-style-capsule-item',
|
|||
|
|
'tree-horizontal': 'hierarchy-tree-lr-tech-style-capsule-item',
|
|||
|
|
'mindmap': 'hierarchy-mindmap-branch-gradient-capsule-item',
|
|||
|
|
'sequence-roadmap': 'sequence-roadmap-vertical-simple',
|
|||
|
|
'sequence-zigzag': 'sequence-horizontal-zigzag-simple',
|
|||
|
|
'sequence-horizontal': 'sequence-horizontal-zigzag-simple',
|
|||
|
|
'relation-sankey': 'relation-sankey-simple',
|
|||
|
|
'relation-circle': 'relation-circle-icon-badge',
|
|||
|
|
'compare-binary': 'compare-binary-horizontal-simple-vs',
|
|||
|
|
'compare-swot': 'compare-swot',
|
|||
|
|
'compare-table': 'compare-table-simple',
|
|||
|
|
'quadrant-quarter': 'quadrant-quarter-simple-card',
|
|||
|
|
'statistic-card': 'list-grid-compact-card',
|
|||
|
|
'chart-bar': 'chart-bar-plain-text',
|
|||
|
|
'chart-column': 'chart-column-simple',
|
|||
|
|
'chart-line': 'chart-line-plain-text',
|
|||
|
|
'chart-area': 'chart-area-simple',
|
|||
|
|
'chart-pie': 'chart-pie-plain-text',
|
|||
|
|
'chart-doughnut': 'chart-pie-donut-plain-text'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
for (const [key, value] of Object.entries(TEMPLATE_MAPPING)) {
|
|||
|
|
const regex = new RegExp(`infographic\\s+${key}(?=\\s|$)`, 'i');
|
|||
|
|
if (regex.test(syntaxContent)) {
|
|||
|
|
console.log(`[Debug] 模板映射: ${key} -> ${value}`);
|
|||
|
|
syntaxContent = syntaxContent.replace(regex, `infographic ${value}`);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const { Infographic } = AntVInfographic;
|
|||
|
|
const instance = new Infographic({
|
|||
|
|
container: '#infographic-container',
|
|||
|
|
padding: 24,
|
|||
|
|
});
|
|||
|
|
instance.render(syntaxContent);
|
|||
|
|
console.log('[Debug] 渲染完成');
|
|||
|
|
|
|||
|
|
// 渲染完成后应用样式
|
|||
|
|
setTimeout(() => {
|
|||
|
|
applyStyles();
|
|||
|
|
}, 300);
|
|||
|
|
} catch (error) {
|
|||
|
|
container.innerHTML = '<div style="color: red; padding: 20px;">⚠️ 渲染错误: ' + error.message + '</div>';
|
|||
|
|
console.error(error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 页面加载后自动渲染
|
|||
|
|
window.onload = function () {
|
|||
|
|
setTimeout(reRender, 500);
|
|||
|
|
};
|
|||
|
|
</script>
|
|||
|
|
</body>
|
|||
|
|
|
|||
|
|
</html>
|