You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

滚动时为下方出现背景图的#logo-icon添加.inverted类的实现问题

问题

我有一个固定元素#logo-icon,需要在用户滚动页面时,当任何带有背景图的div出现在该元素下方时,为其添加.inverted类,但当前编写的代码无法正常运行。

原实现代码

// Select the target element
var logoIcon = document.querySelector('#logo-icon');

// Create a new Intersection Observer instance
var observer = new IntersectionObserver(function(entries) {
  entries.forEach(function(entry) {
    // Check if the target element is intersecting with any other element
    if (entry.isIntersecting) {
      // Check if the intersecting element or its children have a background image
  var intersectingElement = entry.target;
  var hasBackgroundImage = checkBackgroundImage(intersectingElement);

  if (hasBackgroundImage) {
    // Add the "inverted" class to the logoIcon element
    logoIcon.classList.add('inverted');
  } else {
    // Remove the "inverted" class from the logoIcon element
    logoIcon.classList.remove('inverted');
  }
}
  });
}, { threshold: 0.5 });

// Start observing the logoIcon element
observer.observe(logoIcon);

// Function to check if an element or its children have a background image
function checkBackgroundImage(element) {
  // Check if the element itself has a background image
  var computedStyle = window.getComputedStyle(element);
  if (computedStyle.getPropertyValue('background-image') !== 'none') {
return true;
  }

  // Check if any child element has a background image
  var childElements = element.children;
  for (var i = 0; i < childElements.length; i++) {
var childComputedStyle = window.getComputedStyle(childElements[i]);
if (childComputedStyle.getPropertyValue('background-image') !== 'none') {
  return true;
    }
  }

  return false;
}

问题根源

你的代码逻辑完全搞反了:

  • 你现在监听的是#logo-icon自身与视口的交叉状态,entry.target始终是#logo-icon,所以你一直在检查logo元素本身有没有背景图,而非出现在它下方的背景图元素。
  • Intersection Observer默认监测目标元素和视口的交叉,无法直接实现"目标元素与其他页面元素交叉"的检测。

修复方案

要实现需求,需要反过来操作:监听页面中所有带背景图的元素,当它们出现在视口且位置处于logo下方时,切换logo的类。以下是修复后的代码:

var logoIcon = document.querySelector('#logo-icon');
// 获取页面中所有div,过滤出带有背景图的元素
var targetBgElements = Array.from(document.querySelectorAll('div')).filter(el => {
  const computedStyle = window.getComputedStyle(el);
  return computedStyle.backgroundImage !== 'none';
});

// 创建Intersection Observer实例
var observer = new IntersectionObserver(function(entries) {
  // 判断是否存在可见且处于logo下方的背景图元素
  var hasBgBelowLogo = entries.some(entry => {
    if (!entry.isIntersecting) return false;
    
    const logoRect = logoIcon.getBoundingClientRect();
    const elRect = entry.target.getBoundingClientRect();
    // 元素顶部 >= logo底部,说明元素在logo下方
    return elRect.top >= logoRect.bottom;
  });

  logoIcon.classList.toggle('inverted', hasBgBelowLogo);
}, { 
  threshold: 0.1, // 元素进入视口10%即触发检测
  rootMargin: '0px 0px -100% 0px' // 仅监测视口内的元素
});

// 开始监听所有符合条件的背景图元素
targetBgElements.forEach(el => observer.observe(el));

// 可选:窗口大小变化或动态添加元素时,重新更新监听列表
window.addEventListener('resize', () => {
  // 先取消原有监听
  targetBgElements.forEach(el => observer.unobserve(el));
  // 重新筛选元素
  targetBgElements = Array.from(document.querySelectorAll('div')).filter(el => {
    const computedStyle = window.getComputedStyle(el);
    return computedStyle.backgroundImage !== 'none';
  });
  // 重新添加监听
  targetBgElements.forEach(el => observer.observe(el));
});

补充说明

  • 如果背景图元素是动态生成的,需要在元素添加后重复执行"筛选+监听"的逻辑
  • 可调整threshold和rootMargin参数,优化检测的灵敏度和范围
  • 也可以给#logo-icon下方创建一个固定位置的不可见占位元素(如高度1px、与logo同宽),直接监听该占位元素与背景图元素的交叉,逻辑会更简洁

内容的提问来源于stack exchange,提问作者lnvrt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 11:17:35