在滚动上替换img src

时间:2017-10-17 23:12:10

标签: javascript jquery

我正在尝试替换 logo-text-black src属性,以便svg img在用户滚动时更改。是否可以将其添加到我当前的脚本中?

img / logo-text-white.svg //顶级状态

img / logo-text-black.svg //滚动状态

HTML

<nav class="navbar navbar-default navbar-fixed-top">
  <div class="navbar-header">
  <a href="#top"><img class="logo" src="img/logo.svg"></a>
   <a href="#top"><img class="logo-text" src="img/logo-text-white.svg">
 </a>
 </div>
</nav>

JS

$(window).scroll(function() {
   var value = $(this).scrollTop();
   if (value > 100)
   $(".navbar-default").css("background", "white"); // Scroll State
   else
  $(".navbar-default").css("background", "transparent"); // Top state
});

2 个答案:

答案 0 :(得分:4)

要替换图像源,您可以使用jQuery .attr方法:

var initialSrc = "img/logo.svg";
var scrollSrc = "img/logo-text-black.svg";

$(window).scroll(function() {
   var value = $(this).scrollTop();
   if (value > 100)
      $(".logo").attr("src", scrollSrc);
   else
      $(".logo").attr("src", initialSrc);
});

此方法在HTML中只需要一个<img>logo类:

<nav class="navbar navbar-default navbar-fixed-top">
  <div class="navbar-header">
    <a href="#top"><img class="logo" src="img/logo.svg"></a>
 </div>
</nav>

答案 1 :(得分:1)

忽略这样一个事实,即问题的简单答案是你在使用jQuery时使用.attr函数来更改元素的属性,这就是我将如何完成你所提出的任务。问题

首先,我将所有这些放在一个函数中(主要是将变量和逻辑与其他页面脚本分开以防止干扰)。

我的下一个建议是在两个或更多CSS类中实现背景颜色更改。这样可以简化JavaScript,并将样式部分保留在样式区域中。

接下来,我喜欢为我的“魔术词”制作常量变量,这样如果我改变后面使用的单词,我只需要在代码中更改单词一次,而不是在任何地方使用单词。

// cache the magic words
const DARK  = 'dark';
const LIGHT = 'light';

我会将图像源放入一个对象中,其中键是与这些源相关联的魔术词。这样可以在以后快速方便地查找。

// define our different sources for easy access later
const sources = {
  light: "http://via.placeholder.com/150x50/fff/000?text=logo",
  dark:  "http://via.placeholder.com/150x50/000/fff?text=logo"
};

之后我会预先加载图像以防止第一次更改源时出现视觉延迟。

// pre-load the images to prevent jank
document.body.insertAdjacentHTML('beforeend', `
  <div style="display: none!important">
    <img src="${ sources[LIGHT] }">
    <img src="${ sources[DARK] }">
  </div>
`);

请务必注意,执行滚动任务可能会导致问题。

主要问题是:

  • 效果可能是阻塞,这意味着进程繁重的任务将导致“滚动jank”。这是与页面滚动方式存在视觉上不一致的地方。
  • 当已经有滚动事件侦听器执行时,可以触发滚动事件。这可能导致两次执行相互干扰。

解决这些问题很容易:

  • 要防止滚动抖动,请在setTimeout调用中包装处理程序。这将把处理程序的执行移动到堆栈的顶部,以便在下一个方便时执行。
  • 要防止多个处理程序同时运行,请在处理程序外部定义“状态”变量以跟踪执行状态。

    当事件处理程序执行时,此变量将设置为true,而当没有事件处理程序执行时,此变量将设置为false。处理程序执行开始时,检查状态变量的值:

    • 如果是true,则取消执行此处理程序调用。
    • 如果是false,请将状态设置为true并继续。

    只需确保无论您何时退出该功能,您都可以重置状态变量。

      // define our scroll handler
      const scroll_handler = _ => setTimeout(_ => {
        // if we are already handling a scroll event, we don't want to handle this one.
        if (scrolling) return;
        scrolling = true;
    
        // determine which theme should be shown based on scroll position
        const new_theme = document.documentElement.scrollTop > 100 ? DARK : LIGHT;
    
        // if the current theme is the theme that should be shown, cancel execution
        if (new_theme === theme) {
          scrolling = false;
          return;
        }
    
        // change the values
        logo.src = sources[new_theme];
        el.classList.remove(theme);
        el.classList.add(new_theme);
    
        // update the state variables with the current state
        theme = new_theme;
        scrolling = false;
      });
    

之后,只需分配事件监听器。

这一切都在一起:

function navbarSwitcher(el) {
  // cache the reference to the logo element for use later
  const logo  = el.querySelector('.logo');
  
  // cache the magic words
  const DARK  = 'dark';
  const LIGHT = 'light'

  // define our state variables
  let scrolling = false;
  let theme = LIGHT;

  // define our different sources for easy access later
  const sources = {
    light: "http://via.placeholder.com/150x50/fff/000?text=logo",
    dark:  "http://via.placeholder.com/150x50/000/fff?text=logo"
  };
  
  // pre-load the images to prevent jank
  document.body.insertAdjacentHTML('beforeend', `
    <div style="display: none!important">
      <img src="${ sources[LIGHT] }">
      <img src="${ sources[DARK] }">
    </div>
  `);

  // define our scroll handler
  const scroll_handler = _ => setTimeout(_ => {
    // if we are already handling a scroll event, we don't want to handle this one.
    if (scrolling) return;
    scrolling = true;

    // determine which theme should be shown based on scroll position
    const new_theme = document.documentElement.scrollTop > 100 ? DARK : LIGHT;

    // if the current theme is the theme that should be shown, cancel execution
    if (new_theme === theme) {
      scrolling = false;
      return;
    }

    // change the values
    logo.src = sources[new_theme];
    el.classList.remove(theme);
    el.classList.add(new_theme);

    // update the state variables with the current state
    theme = new_theme;
    scrolling = false;
  });

  // assign the event listener to the window
  window.addEventListener('scroll', scroll_handler);
}

// attach our new plugin to the element
navbarSwitcher(document.querySelector('.wrap'));
body {
  height: 200vh;
}
.wrap {
  width: 100%;
  position: fixed;
}
.wrap.light {
  background-color: white;
}
.wrap.dark {
  background-color: black;
}
<div class="wrap light">
  <img class="logo" src="http://via.placeholder.com/150x50/fff/000?text=logo">
</div>