如何解决jQuery滚动触发的甜甜圈图改页面加载渲染不生效问题?
问题描述
我是jQuery初学者,修改站点统计用的甜甜圈(donut)图表脚本一直没调试成功。当前图表仅在页面滚动时才会触发渲染,不滚动页面就完全没有反应。我希望实现页面加载完成后就直接渲染图表,因此尝试将原有的滚动触发逻辑替换为页面加载触发,但修改没有生效,请问问题出在哪里?
原始脚本代码
/* Tokan Graph */ if ($("#tokensale-part").length > 0) { function tokan_graph() { var scrollDistance = $(window).scrollTop(); var scrollDistance1 = $('#tokensale-part').offset().top - 100; if (scrollDistance >= (scrollDistance1 - 100) && scrollDistance <= (scrollDistance1 + 100)) { $('.donut').listtopie({ startAngle: 270, strokeWidth: 5, hoverEvent: true, hoverBorderColor: '#16d5ff', hoverAnimate: false, drawType: 'round', speedDraw: 150, hoverColor: '#ffffff', textColor: '#3d1f94', strokeColor: '#f2f8fe', textSize: '18', hoverAnimate: true, marginCenter: 85, }); } } $(window).scroll(function() { tokan_graph(); }) $(window).on("resize", function() { $(window).resize(function() { if (w != $(window).width()) { if ($(window).width() < 767) { $('.donut').listtopie('refresh'); } w = $(window).width(); } }); }) $(".token-graph").addClass("token-graph-right"); } /* Tokan Graph End */
已做的修改
我将代码中的$(window).scroll(function(){修改为$(window).onload(function(){,但图表依然只有滚动页面时才会加载,没有达到预期效果。
不生效的核心原因
触发方法写法完全错误,没有实际执行效果
jQuery本身没有封装.onload()这个快捷方法,你写的$(window).onload(function(){})是无效调用,根本不会执行里面的逻辑。而原来绑定在window上的scroll事件监听代码并没有被移除,所以系统还是只靠滚动事件触发图表渲染。
补充:如果要实现jQuery下的页面加载完成绑定,正确写法是$(window).on('load', function(){}),和原生JS的window.onload功能一致,但jQuery里不能直接把onload当方法名接在后面写。原有渲染逻辑的滚动位置判断没有适配页面加载场景
原来的tokan_graph函数内部绑定了强校验:只有当前滚动位置落在图表元素上下100px的区间内,才会执行图表渲染。哪怕你正确写了页面加载的触发代码,如果页面刚加载时的滚动位置没落在这个区间内,渲染逻辑依然不会执行。
修正方法
不需要完全重构原有逻辑,只需要调整三个点就能实现需求:
- 把图表渲染逻辑从滚动判断中抽离,支持手动调用
- 用正确的页面加载完成绑定写法,在加载完成后手动触发一次渲染
- 给窗口大小变化的逻辑补上缺失的变量声明、去掉重复嵌套的事件绑定,避免性能损耗
修改后的可运行代码:
/* Tokan Graph 修正版 */ if ($("#tokensale-part").length > 0) { // 抽离独立的图表渲染函数 function renderDonut() { $('.donut').listtopie({ startAngle: 270, strokeWidth: 5, hoverEvent: true, hoverBorderColor: '#16d5ff', hoverAnimate: false, drawType: 'round', speedDraw: 150, hoverColor: '#ffffff', textColor: '#3d1f94', strokeColor: '#f2f8fe', textSize: '18', hoverAnimate: true, marginCenter: 85, }); } // 页面加载完成后直接触发渲染 $(window).on('load', function() { renderDonut(); }) // 修正resize逻辑:提前声明变量、去掉嵌套重复绑定 let windowWidth = $(window).width(); $(window).resize(function() { const currentWidth = $(window).width(); if (windowWidth !== currentWidth) { if (currentWidth < 767) { $('.donut').listtopie('refresh'); } windowWidth = currentWidth; } }) $(".token-graph").addClass("token-graph-right"); } /* Tokan Graph End */
额外的代码优化提醒
- 原代码中resize事件写了两层嵌套绑定,每次窗口大小变化都会新增一个新的resize监听,长期运行会造成不必要的性能消耗,上面的修正版已经把冗余嵌套去掉了。
- 原代码中判断窗口宽度用的
w变量没有提前声明,在严格模式下会触发未定义变量的报错,修正版已经补上了变量声明。
内容的提问来源于stack exchange,提问作者Giovanottin

