触发功能,当用户滚动元件进入视 - 香草的JavaScript

问题描述 投票:2回答:2

我写这动画的柱状图功能。目前,这一行动被触发在页面加载,但我只希望当我到达的元素就引发 - 否则用户不会看到动画。我想通过香草JavaScript来实现这一目标,这可能吗?

这里是我的标记:

<div class="section">
  section
</div>
<div class="section">
  section
</div>
<div class="section">
  section
</div>
<div class="section">
  section
  <ul class="skills__list">
    <li class="skills__list-item">
      <div class="bar">
        <span>HTML</span>
        <div class="bar__inner" data-percent="90%"></div>
      </div>
    </li>
    <li class="skills__list-item">
      <div class="bar">
        <span>css</span>
        <div class="bar__inner" data-percent="80%"></div>
      </div>
    </li>
    <li class="skills__list-item">
      <div class="bar">
        <span>Javascript</span>
        <div class="bar__inner" data-percent="60%"></div>
      </div>
    </li>
    <li class="skills__list-item">
      <div class="bar">
        <span>UI design</span>
        <div class="bar__inner" data-percent="70%"></div>
      </div>
    </li>
    <li class="skills__list-item">
      <div class="bar">
        <span>sketch</span>
        <div class="bar__inner" data-percent="50%"></div>
      </div>
    </li>
    <li class="skills__list-item">
      <div class="bar">
        <span>Photoshop</span>
        <div class="bar__inner" data-percent="80%"></div>
      </div>
    </li>
    <li class="skills__list-item">
      <div class="bar">
        <span>Illustrator</span>
        <div class="bar__inner" data-percent="90%"></div>
      </div>
    </li>
  </ul>
</div>

这里是SCSS:

*{
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

.section {
  padding: 20px;
  font-size: 30px;
  font-family: sans-serif;
  text-transform: uppercase;
  height: 400px;
  &:nth-child(1){
    background-color: #ddd;
  }
  &:nth-child(2){
    background-color: #aaa;
  }
  &:nth-child(3){
    background-color: #bbb;
  }
  &:nth-child(4){
    background-color: #000;
  }
}

.skills__list-item {
  & + .skills__list-item {
    margin-top: 20px;
  }
}

// bar chart styles
.bar {
  position: relative;
  width: 100%;
  height: 28px;
  overflow: hidden;
  background-color: blue;

  span {
    position: absolute;
    z-index: 9;
    display: flex;
    align-items: center;
    height: 100%;
    padding: 10px;
    color: #fff;
    background-color: red;
  }

  &__inner {
    display: flex;
    justify-content: flex-end;
    width: 0;
    height: 100%;
    background-color: green;
    transform-origin: 0 100%;
    transition: width 0.6s linear;

    &::after {
      content: attr(data-percent);
      align-self: center;
      padding-right: 20px;
      color: #fff;
    }
  }
}

这里是JavaScript:

const bars = document.querySelectorAll('.bar__inner');


Array.from(bars).forEach((bar, index) => {
  setTimeout(() => {
    const eachBar = bar;
    eachBar.style.width = bar.dataset.percent;
  }, index * 400);
});

这里有一个工作示例Codepen

javascript ecmascript-6 viewport
2个回答
3
投票

您可以按照网站very helpful tipGomakethings.com

这表明,你可以使用getBoundingClientRect()方法来实现自己的目标:

// Get the an HTML element
var element = document.querySelector('<a selector>');

// Get its bounding client rectangle
var bounding = element.getBoundingClientRect();

用它来建立它检查如果元素中视客户通过检索边框的功能(好吧,代码可以改进的,它只是一个演示):

function isInViewPort(element) {
    // Get the bounding client rectangle position in the viewport
    var bounding = element.getBoundingClientRect();

    // Checking part. Here the code checks if it's *fully* visible
    // Edit this part if you just want a partial visibility
    if (
        bounding.top >= 0 &&
        bounding.left >= 0 &&
        bounding.right <= (window.innerWidth || document.documentElement.clientWidth) &&
        bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight)
    ) {
        console.log('In the viewport! :)');
        return true;
    } else {
        console.log('Not in the viewport. :(');
        return false;
    }
}

最后,添加上调用上述功能scroll事件的事件监听器:

window.addEventListener('scroll', function (event) {
    if (isInViewport(theElementToWatch)) {
      // update the element display
    }
}, false);

根据浏览器兼容性displayed by the MDN pagegetBoundingClientRect()完全由铬和Firefox(> = 3.5)的支持。这里所提供的解决方案是最常用的浏览器(它是未知的一些移动版本)的全面支持。

Can I use...网站所提供的一个,移动浏览器(Chrome浏览器,Firefox等)完全从一个给定的版本支持该方法,至少。

最后,你可以记住一个还是实验性的解决方案,旨在取代使用方法getBoundingClientRect()的,路口观察API(见汤姆·M的答案)。 The MDN related page解释了原因:

实现过去参与的事件处理程序交集检测和循环调用的方法,如Element.getBoundingClientRect()建立每个受影响的元素所需的信息。由于所有这些代码在主线程上运行,这些甚至可以导致性能问题。当一个站点加载这些测试,事情可以得到彻头彻尾的丑陋。


1
投票

您可以使用IntersectionObserver API此。

const observer = new IntersectionObserver((entries) => { 
    entries.forEach((entry) => {
        console.log(entry.target);
        // your callback here
    })
}); 

observer.observe(document.querySelector('.skills__list-item'));

胸怀Browser support虽然,它不是在IE,Safari和Opera Mini的支持情况。

enter image description here

如果你想支持IE7 +,你可以使用,虽然the polyfill provided by the W3C

资源

© www.soinside.com 2019 - 2024. All rights reserved.