Spring+Thymeleaf+JavaScript实现动态水平堆叠柱状图问题
飞盘高尔夫回合图表问题解决方案
一、仅首回合显示图表的修复
你遇到的问题大概率是因为所有回合的图表容器复用了同一个ID,JS通过getElementById只会拿到第一个匹配元素。改成动态生成唯一标识+遍历初始化就能解决:
1. Thymeleaf循环里生成唯一容器ID
利用Thymeleaf的循环状态变量stat.index或者回合ID,给每个图表容器分配唯一ID,同时绑定对应的数据:
<div th:each="round, stat : ${userRounds}"> <div class="round-card"> <h4>回合 #[[${stat.count}]]</h4> <!-- 绑定分数和标准杆数据到data属性,同时生成唯一ID --> <div id="chart-[[${stat.index}]]" class="round-chart" data-scores='[[${#jsonserialize(round.holeScores)}]]' data-pars='[[${#jsonserialize(round.pars)}]]' style="height: 220px; margin: 10px 0;"></div> </div> </div>
2. JS遍历所有容器初始化图表
不要只初始化第一个ID,而是通过类选择器拿到所有图表容器,逐个处理:
document.addEventListener('DOMContentLoaded', function() { // 拿到所有回合图表容器 const chartElements = document.querySelectorAll('.round-chart'); chartElements.forEach((el, idx) => { // 从data属性取当前回合的分数和标准杆 const scores = JSON.parse(el.dataset.scores); const pars = JSON.parse(el.dataset.pars); // 初始化水平柱状图(这里以Chart.js为例,换其他库逻辑类似) new Chart(el, { type: 'bar', data: { labels: scores.map((_, i) => `球洞 ${i+1}`), datasets: [{ data: scores, backgroundColor: scores.map((score, i) => getScoreColor(score, pars[i])), borderWidth: 1 }] }, options: { indexAxis: 'y', // 设为水平柱状图 responsive: true, plugins: { legend: { display: false } } // 隐藏图例,按需调整 } }); }); });
二、分数动态着色实现
写一个简单的判断函数,根据分数和标准杆的关系返回对应颜色:
function getScoreColor(score, par) { // 一杆进洞优先判断 if (score === 1) return '#27ae60'; // 绿色 const diff = score - par; if (diff === -1) return '#3498db'; // 蓝色(低于标准杆1杆) if (diff === 0) return '#ecf0f1'; // 浅灰/无颜色(标准杆) if (diff === 1) return '#f39c12'; // 橙色(高于标准杆1杆) // 其他情况可选默认色,比如高于标准杆多杆用红色 return '#e74c3c'; }
关键注意点
- 确保图表库脚本在页面底部加载,或者放在
DOMContentLoaded回调里,避免DOM未渲染就执行代码 - 测试时检查每个回合的data属性是否正确绑定了JSON格式的分数数据
- 如果不用Chart.js,替换成你用的图表库的初始化逻辑即可,核心是遍历每个容器
内容的提问来源于stack exchange,提问作者Kayd Anderson
相关产品推荐
相关产品推荐

