Uncaught TypeError报错求助:Stream Elements粉丝进度条事件触发异常
解决Stream Elements粉丝进度条报错:Uncaught TypeError: Cannot read properties of null (reading 'getBoundingClientRect')
错误原因分析
- DOM选择器大小写不匹配:HTML中进度条元素的ID是
Bar(首字母大写),但JS代码里用的是#bar(全小写),导致querySelector返回null,调用getBoundingClientRect时触发报错。 - 未定义变量
fill:代码中直接使用fill.style但未声明该变量,无法找到要修改的进度条元素。 onSessionUpdate数据结构错误:该事件的obj.detail.session是会话对象,实际数据在data属性下,直接取值会导致data["follower-goal"]为undefined。- 除数为0风险:如果
state.goal.value初始为0,计算进度时会触发除法错误。
修复方案与完整代码
修正后的JavaScript代码
let state = { "goal": { "value": 0 } }; window.addEventListener('onWidgetLoad', function(obj) { let data = obj.detail.session.data; let fieldData = obj.detail.fieldData; // 避免goal_total为0的情况 state.goal.value = fieldData.goal_total || 1; progress(data); }); window.addEventListener('onSessionUpdate', function(obj) { // 修正数据获取路径 let data = obj.detail.session.data; progress(data); }); // 监听新粉丝事件,触发进度更新 window.addEventListener('onEventReceived', function(obj) { const event = obj.detail.event; // 判断是否是新粉丝事件 if (event.type === 'follower') { const data = obj.detail.session.data; progress(data); } }); let progress = (data) => { // 匹配HTML中的ID大小写 const barContainer = document.querySelector("#Bar"); if (!barContainer) return; // 元素不存在时直接返回,避免报错 const maxWidth = barContainer.getBoundingClientRect().width; // 确保follower-goal数据存在,默认值设为0 let count = data["follower-goal"]?.amount || 0; let p = 0; // 避免除以0 if (state.goal.value > 0) { p = (count / state.goal.value) * maxWidth; } // 进度不超过最大值 if (count >= state.goal.value) { p = maxWidth; } // 定义fill为进度条元素(这里就是Bar本身) const fill = barContainer; fill.style.setProperty('width', `${p}px`); // 加上单位px,确保样式生效 };
修正后的CSS代码
#Bar { transition: 3s width; /* 初始宽度设为0,避免加载时满宽 */ width: 0; }
保持不变的HTML(SVG)代码
<?xml version="1.0" encoding="UTF-8"?> <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 961.66 61.72"> <defs> <style> .cls-1 { fill: url(#linear-gradient-2); } .cls-2 { fill: #f15a24; } .cls-3 { opacity: .26; } .cls-4 { fill: url(#linear-gradient-3); } .cls-5 { fill: url(#linear-gradient); } .cls-6 { fill: url(#linear-gradient-4); } </style> <linearGradient id="linear-gradient" x1="480.83" y1="0" x2="480.83" y2="61.72" gradientUnits="userSpaceOnUse"> <stop offset="0" stop-color="#fff" stop-opacity=".3"/> <stop offset=".37" stop-color="#f7f7f7" stop-opacity=".29"/> <stop offset=".56" stop-color="#ddd" stop-opacity=".26"/> <stop offset=".71" stop-color="#b0b0b0" stop-opacity=".21"/> <stop offset=".85" stop-color="#707070" stop-opacity=".13"/> <stop offset=".96" stop-color="#1e1e1e" stop-opacity=".04"/> <stop offset="1" stop-color="#000" stop-opacity="0"/> </linearGradient> <linearGradient id="linear-gradient-2" x1="0" y1="30.86" x2="961.66" y2="30.86" gradientUnits="userSpaceOnUse"> <stop offset="0" stop-color="#fff" stop-opacity=".4"/> <stop offset=".37" stop-color="#fff" stop-opacity=".34"/> <stop offset="1" stop-color="#fff" stop-opacity=".2"/> </linearGradient> <linearGradient id="linear-gradient-3" x1="480.83" y1="61.72" x2="480.83" y2="0" gradientUnits="userSpaceOnUse"> <stop offset="0" stop-color="#fff" stop-opacity="0"/> <stop offset="1" stop-color="#fff"/> </linearGradient> <linearGradient id="linear-gradient-4" x1="480.83" y1="0" x2="480.83" y2="61.72" xlink:href="#linear-gradient"/> </defs> <g id="BG"> <rect class="cls-5" x="0" width="961.66" height="61.72"/> <path class="cls-1" d="M957.83,3.84V57.89H3.84V3.84H957.83M961.66,0H0V61.72H961.66V0h0Z"/> </g> <g> <rect id="Bar" class="cls-2" x="0" width="961.66" height="61.72"/> <g class="cls-3"> <rect class="cls-4" x="0" width="961.66" height="61.72"/> </g> <path class="cls-6" d="M957.75,3.91V57.81H3.91V3.91H957.75M961.66,0H0V61.72H961.66V0h0Z"/> </g> </svg>
额外说明
- 新增了
onEventReceived监听,专门处理新粉丝事件,确保有新粉丝时立即更新进度条。 - 增加了元素存在性检查和默认值处理,避免因数据缺失或DOM未加载完成导致的报错。
- CSS中给进度条添加了初始宽度0,符合进度条从0开始的逻辑。
内容的提问来源于stack exchange,提问作者Qusbarg
相关产品推荐
相关产品推荐

