DIVI框架下JavaScript中IF语句无法获取函数返回值问题
我是初级开发者,正在使用DIVI框架实现元素进入用户视口时触发动画的功能。此前已有成功经验,但简化代码后,check_if_in_view函数的返回值无法被IF语句捕获,始终返回false。使用$().each循环是因为存在多个不同ID的元素,不使用该循环会出现无法读取元素顶部位置的错误。需要问题解决方法及性能优化建议。
全局JS代码
//Getting element and window parameters var $window = $(window); function check_if_in_view(el) { //Da finire var $element = $(el); var window_height = $window.height(); var window_top_position = $window.scrollTop(); var window_bottom_position = (window_top_position + window_height); $(el).each(function() { var element_height = $(this).outerHeight(); var element_top_position = $(this).offset().top; var element_bottom_position = (element_top_position + element_height); console.log($(this).attr('id')); //check to see if this current container is within viewport if ((element_bottom_position >= window_top_position) && (element_top_position <= window_bottom_position)) { console.log('true'); return true; } else { console.log('false'); return false; } }); };
页面专属JS代码
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <script> $('.fadeInLeft').css({'right' : '700px', 'opacity' : '0'}); $('.fadeInRight').css({'left' : '700px', 'opacity' : '0'}); function animateFadeLeft(el) { $(el).each(function() { if(check_if_in_view($(this))) { console.log('sono dentro') $(this).animate({right: '0px', opacity : '1'}, 1200); } }); } $(window).on('DOMContentLoaded load resize scroll', function(){ animateFadeLeft('.fadeInLeft'); animateFadeLeft('.fadeInRight'); //To add }); </script>
核心原因
check_if_in_view函数里的$(el).each()循环中,return true/false仅会终止当前循环的单次迭代,不会将值返回给外层的check_if_in_view函数,导致外层函数默认返回undefined,在IF判断中被识别为false。
另外,你在调用check_if_in_view时,已经是在animateFadeLeft的each循环中传入单个元素($(this)),所以check_if_in_view内部完全不需要再做each循环。
修复后的check_if_in_view函数
var $window = $(window); function check_if_in_view(el) { var $element = $(el); var window_height = $window.height(); var window_top_position = $window.scrollTop(); var window_bottom_position = window_top_position + window_height; var element_height = $element.outerHeight(); var element_top_position = $element.offset().top; var element_bottom_position = element_top_position + element_height; // 直接返回视口判断结果 return (element_bottom_position >= window_top_position) && (element_top_position <= window_bottom_position); };
修复后,函数会直接返回布尔值,IF语句就能正确捕获结果,触发动画逻辑。
避免重复计算窗口参数:窗口高度、滚动位置在每次事件触发时只需计算一次,不需要在每个元素的检查函数里重复计算。可以把这些参数提前算出后传递给检查函数,减少冗余计算:
$(window).on('DOMContentLoaded load resize scroll', function(){ // 一次性计算窗口参数 var window_height = $window.height(); var window_top_position = $window.scrollTop(); var window_bottom_position = window_top_position + window_height; animateFadeLeft('.fadeInLeft', window_top_position, window_bottom_position); animateFadeLeft('.fadeInRight', window_top_position, window_bottom_position); }); // 修改动画函数,接收窗口参数 function animateFadeLeft(el, windowTop, windowBottom) { $(el).each(function() { if(check_if_in_view($(this), windowTop, windowBottom)) { $(this).animate({right: '0px', opacity : '1'}, 1200); } }); } // 修改检查函数,接收窗口参数 function check_if_in_view(el, windowTop, windowBottom) { var $element = $(el); var element_height = $element.outerHeight(); var element_top_position = $element.offset().top; var element_bottom_position = element_top_position + element_height; return (element_bottom_position >= windowTop) && (element_top_position <= windowBottom); }防止动画重复触发:给已完成动画的元素添加标记(比如自定义数据属性),避免滚动时反复执行动画逻辑:
function animateFadeLeft(el, windowTop, windowBottom) { $(el).each(function() { // 检查是否已执行过动画 if(!$(this).data('animated') && check_if_in_view($(this), windowTop, windowBottom)) { $(this).data('animated', true).animate({right: '0px', opacity : '1'}, 1200); } }); }节流事件触发频率:滚动、resize事件触发极频繁,用节流函数限制处理逻辑的执行频率(比如每100ms执行一次),降低性能消耗:
// 简单节流函数实现 function throttle(func, delay) { let lastExecuteTime = 0; return function(...args) { const now = Date.now(); if(now - lastExecuteTime >= delay) { lastExecuteTime = now; func.apply(this, args); } } } // 用节流包裹事件处理函数 $(window).on('DOMContentLoaded load resize scroll', throttle(function(){ var window_height = $window.height(); var window_top_position = $window.scrollTop(); var window_bottom_position = window_top_position + window_height; animateFadeLeft('.fadeInLeft', window_top_position, window_bottom_position); animateFadeLeft('.fadeInRight', window_top_position, window_bottom_position); }, 100));优先使用CSS动画:CSS动画性能优于JS动画,建议用
transition或@keyframes配合类名切换实现动画:.fadeInLeft { right: 700px; opacity: 0; transition: all 1.2s ease; } .fadeInLeft.active { right: 0; opacity: 1; } .fadeInRight { left: 700px; opacity: 0; transition: all 1.2s ease; } .fadeInRight.active { left: 0; opacity: 1; }对应的JS逻辑简化为:
function animateFadeLeft(el, windowTop, windowBottom) { $(el).each(function() { if(!$(this).hasClass('active') && check_if_in_view($(this), windowTop, windowBottom)) { $(this).addClass('active'); } }); }
内容的提问来源于stack exchange,提问作者Leonardo Di Silvestre

