Google Chart API每次调用draw()都会新增div?如何阻止?
问题描述
每次调用chart.draw()更新Google DataTable时,页面会重复生成以下元素:
- body标签末尾新增隐藏测量元素:
<div style="position: absolute; top: -1000px; left: -1000px; white-space: nowrap; display: none;"><svg></svg></div> - head标签重复插入Roboto字体链接:
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto%7CRoboto:medium">
使用的图表加载配置:
google.charts.load('current', { 'packages': ['corechart', 'line', 'controls', 'bar', 'table'] });
该行为导致页面格式混乱,需阻止重复元素生成。
解决方案
1. 手动预加载Roboto字体,避免重复插入link标签
在页面head中手动添加一次Roboto字体链接,Google Charts检测到字体已加载后,不会在每次draw时重复插入:
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto%7CRoboto:medium">
2. 复用图表实例,避免重复生成测量元素
不要每次调用draw时创建新的图表实例,仅初始化一次,后续更新数据后复用该实例执行draw:
// 全局保存图表实例 let chartInstance; google.charts.load('current', { 'packages': ['corechart', 'line', 'controls', 'bar', 'table'] }); google.charts.setOnLoadCallback(() => { // 仅初始化一次图表 chartInstance = new google.visualization.LineChart(document.getElementById('your-chart-container')); // 初始绘制 drawChart(); // 每秒更新数据并复用实例绘制 setInterval(() => { const updatedData = getUpdatedDataTable(); // 替换为你的数据更新逻辑 chartInstance.draw(updatedData, yourChartOptions); }, 1000); });
3. 指定自定义字体,禁用自动字体加载
在图表配置选项中明确设置文本字体为系统字体或你已加载的字体,Google Charts将不会自动加载Roboto,也不会生成相关测量元素:
const chartOptions = { textStyle: { fontFamily: 'Arial, Helvetica, sans-serif' // 替换为你需要的字体 }, // 其他图表配置项... };
4. 清理重复生成的元素(治标方案)
如果以上方法无法完全解决,可通过监听DOM变化自动移除重复元素:
// 监听head变化,移除重复的Roboto字体链接 const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.addedNodes.length) { mutation.addedNodes.forEach((node) => { if (node.tagName === 'LINK' && node.href.includes('fonts.googleapis.com/css?family=Roboto')) { const existingLinks = document.querySelectorAll(`link[href="${node.href}"]`); if (existingLinks.length > 1) { node.remove(); } } }); } }); }); observer.observe(document.head, { childList: true }); // 定期清理body末尾多余的隐藏测量div setInterval(() => { const hiddenDivs = document.querySelectorAll('div[style*="position: absolute; top: -1000px"]'); if (hiddenDivs.length > 1) { for (let i = 1; i < hiddenDivs.length; i++) { hiddenDivs[i].remove(); } } }, 1000);
内容的提问来源于stack exchange,提问作者Seth Schaffner
相关产品推荐
相关产品推荐

