javascript - 替换多个类 onScroll?

标签 javascript jquery html css

我一直在研究 horizontal website本周并从这里的社区收到了很多建议和有用的代码(谢谢!)。

我的 JS 技能非常不稳定,但我正在更好地掌握它,我的 CodePen展示了我刚才所拥有的,以及它或多或少完美地工作。我组合了两个单独的函数来帮助 onClick 工作,但这显然对 onScroll 也不起作用。我试图了解最佳实践是什么,因为我仍然不完全理解 JS 的规则。

问题:onScroll active 类激活正常(变成黄色),但 ion-ios-radio-button-on 没有切换到 ion-ios-radio-button-off(反之亦然)。但是,如果您单击图标,它们将完全改变。

我试过弄乱那里的内容,例如添加更多替换/添加/删除属性,但当然它们可能不会起作用,因为我不确定将它们放在哪里。我知道这段代码也可以压缩,但我的技术水平不是那么高。

我一如既往地感谢任何有助于拓宽我知识面的建议和帮助!

// ---

const main = document.querySelector( 'main' );
const nav = document.querySelector( '.bottomnav' );
const setIconState = (icon, state) => icon.className = state ?
    icon.className.replace('button-off', 'button-on') :
    icon.className.replace('button-on', 'button-off')

const toggleIcon = element => {
    const className = element.className;
    element.className = className.indexOf('button-on') > -1 ?
        setIconState(element, false) :
        setIconState(element, true);
}

const setIconActiveState = (icon, state) => icon.className = state ?
    icon.className = `${icon.className} active` :
    icon.className = icon.className.replace('active', '')

document.querySelectorAll('.bottomnav a.icon')
    .forEach(icon => {
        icon.onclick = (e) => {
            const {
                target: clickedSpan
            } = e;

            const siblings = [...clickedSpan.parentElement.parentElement.querySelectorAll('a.icon')]
                .filter(sibling => sibling != clickedSpan);

            siblings.forEach(icon => {
                setIconState(icon, false);
                setIconActiveState(icon, false);
            });
            setIconState(clickedSpan, true);
            setIconActiveState(clickedSpan, true);
        };
    });

let scrollend;

function onwheel(){
  
/* When using the scrollwheel, translate Y direction scrolls to X direction. This way scrollwheel users get the benefit of scrolling down to go right, while touch and other users get default behaviour. */
  
  event.preventDefault();
  event.stopImmediatePropagation();
  
  main.scrollLeft += event.wheelDeltaY;
  
}
function onscroll(){
  
  const current = Array.from( main.children ).find(child => {
  
      return child.offsetLeft >= main.scrollLeft - innerWidth / 2;
      
  });
  const link = Array.from( nav.children ).reduce((find, child) => {
    
    child.classList.remove( 'active' );
    
    return find || (child.href.indexOf( current.id ) >= 0 ? child : find);
    
  }, false);
  
  if( link ) link.classList.add( 'active' );
  
  clearTimeout( scrollend );
  scrollend = setTimeout( onscrollend, 100 );
  
}
function onscrollend(){
  
  /* After scrolling ends, snap the appropriate element. This could be done with an animation. */
  clearTimeout( scrollend );
  
  const current = Array.from( main.children ).find(child => {
  
      return child.offsetLeft >= main.scrollLeft - innerWidth / 2;
      
  });
  
  main.scrollLeft = current.offsetLeft;
  
}

/* Bind and initial call */

main.addEventListener( 'wheel', onwheel );
main.addEventListener( 'scroll', onscroll );

onscroll();
html,
body,
main {
    height: 100%;
  scoll-behavior: smooth;
}
body {
    padding: 0;
    margin: 0;
}
main {
    display: flex;
    overflow: auto;
    width: 100%;
    height: 100%;
    scroll-snap-type: x mandatory;
}
main section {
  padding: 1%;
    width: 100%;
    height: 100vh;
    flex: 0 0 100%;
}
.bottomnav {
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
}
.bottomnav a {
    width: 1em;
    height: 1em;
    margin: 1em;
    display: block;
    overflow: hidden;
    color: #888;
    font-size: 26px;
/*     color: transparent;
    border: 1px solid black;
    border-radius: 50%; */
}

.bottomnav a:hover {
      color: #fac123;
    transition: color .5s;
}

.bottomnav a.active {
    color: #fac123;
  transition: color .5s;
}

.card {
  height: 100vh;
}

.cardblack {
  background-color: black;
  color: white;
}
<link href="https://unpkg.com/ionicons@4.5.5/dist/css/ionicons.min.css" rel="stylesheet">

<div class="bottomnav">
  
   <a href="#1" class="icon ion-ios-radio-button-on">Section 1</a>
  <a href="#2" class="icon ion-ios-radio-button-off">Section 2</a>
  <a href="#3" class="icon ion-ios-radio-button-off">Section 3</a>
        </div>
<main>
<section class="card cardwhite" id="1">
      <h2>Section 1</h2>
   </section>
   
   <section class="card cardblack" id="2">
      <h2>Section 2</h2>
   </section>
   
   <section class="card cardwhite" id="3">
      <h2>Section 3</h2>
   </section>
</main>

最佳答案

看起来您可以调用与点击时调用的代码相同的代码:

  setIconState(link, true);
  setIconActiveState(link, true);

所以你可以删除:

  if (link) link.classList.add('active');

这样做有用吗?

const main = document.querySelector('main');
const nav = document.querySelector('.bottomnav');

const setIconState = (icon, state) => icon.className = state ?
  icon.className.replace('button-off', 'button-on') :
  icon.className.replace('button-on', 'button-off')

const toggleIcon = element => {
  const className = element.className;
  element.className = className.indexOf('button-on') > -1 ?
    setIconState(element, false) :
    setIconState(element, true);
}

const setIconActiveState = (icon, state) => icon.className = state ?
  icon.className = `${icon.className} active` :
  icon.className = icon.className.replace('active', '')

document.querySelectorAll('.bottomnav a.icon')
  .forEach(icon => {
    icon.onclick = (e) => {
      const {
        target: clickedSpan
      } = e;

      const siblings = [...clickedSpan.parentElement.parentElement.querySelectorAll('a.icon')]
        .filter(sibling => sibling != clickedSpan);

      siblings.forEach(icon => {
        setIconState(icon, false);
        setIconActiveState(icon, false);
      });
      setIconState(clickedSpan, true);
      setIconActiveState(clickedSpan, true);
    };
  });

let scrollend;

function onwheel() {
  event.preventDefault();
  event.stopImmediatePropagation();

  main.scrollLeft += event.wheelDeltaY;
}

function onscroll() {
  const current = Array.from(main.children).find(child => {

    return child.offsetLeft >= main.scrollLeft - innerWidth / 2;

  });
  
  const link = Array.from(nav.children).reduce((find, child) => {
    child.classList.remove('active');

    return find || (child.href.indexOf(current.id) >= 0 ? child : find);
  }, false);

  setIconState(link, true);
  setIconActiveState(link, true);

  clearTimeout(scrollend);
  scrollend = setTimeout(onscrollend, 100);
}

function onscrollend() {

  /* After scrolling ends, snap the appropriate element. This could be done with an animation. */
  clearTimeout(scrollend);

  const current = Array.from(main.children).find(child => {

    return child.offsetLeft >= main.scrollLeft - innerWidth / 2;

  });

  main.scrollLeft = current.offsetLeft;

}

/* Bind and initial call */

main.addEventListener('wheel', onwheel);
main.addEventListener('scroll', onscroll);

onscroll();
html,
body,
main {
  height: 100%;
  scoll-behavior: smooth;
}

body {
  padding: 0;
  margin: 0;
}

main {
  display: flex;
  overflow: auto;
  width: 100%;
  height: 100%;
  scroll-snap-type: x mandatory;
}

main section {
  padding: 1%;
  width: 100%;
  height: 100vh;
  flex: 0 0 100%;
}

.bottomnav {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.bottomnav a {
  width: 1em;
  height: 1em;
  margin: 1em;
  display: block;
  overflow: hidden;
  color: #888;
  font-size: 26px;
  /*     color: transparent;
    border: 1px solid black;
    border-radius: 50%; */
}

.bottomnav a:hover {
  color: #fac123;
  transition: color .5s;
}

.bottomnav a.active {
  color: #fac123;
  transition: color .5s;
}

.card {
  height: 100vh;
}

.cardblack {
  background-color: black;
  color: white;
}
<link href="https://unpkg.com/ionicons@4.5.5/dist/css/ionicons.min.css" rel="stylesheet">

<div class="bottomnav">
  <a href="#1" class="icon ion-ios-radio-button-on">Section 1</a>
  <a href="#2" class="icon ion-ios-radio-button-off">Section 2</a>
  <a href="#3" class="icon ion-ios-radio-button-off">Section 3</a>
</div>

<main>
  <section class="card cardwhite" id="1">
    <h2>Section 1</h2>
  </section>

  <section class="card cardblack" id="2">
    <h2>Section 2</h2>
  </section>

  <section class="card cardwhite" id="3">
    <h2>Section 3</h2>
  </section>
</main>

关于javascript - 替换多个类 onScroll?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57292111/

相关文章:

javascript - Rails 默认选择单选按钮

javascript - jQuery 的 SlideUp 函数对我来说不能正常工作

javascript - jqGrid 4.0 bindKeys 方法使用上下箭头键移动整个网格

Javascript 设置一个由字符串和另一个变量连接的变量

javascript - 有没有办法从网页激活 Siri?

javascript - 语义用户界面( react ): Responsive vertical menu by changing to horizontal on mobile devices

jquery - 使用 jQuery 添加 XML DOM 元素-可能吗?

javascript - 内容页面中的 JQuery 未执行

html - Bootstrap 折叠面板在展开时变得太大

javascript - 使用 IE 在 Angular 模板中设置 HTML 样式时出现问题