具有CSS滚动捕捉的指示器(点) [英] Indicators (dots) with CSS scroll snap

查看:87
本文介绍了具有CSS滚动捕捉的指示器(点)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用CSS滚动快照构建滚动轮播。



  .carousel {scroll-snap-type:x必选; -webkit-overflow-scrolling:触摸;宽度:100vw;空白:nowrap;溢出-x:滚动;}。轮播> * {display:inline-block; scroll-snap-align:开始;宽度:100vw;高度:100vh;}#x {背景颜色:粉红色;}#y {背景颜色:浅蓝色;}#z {背景颜色:浅灰色;}  

< pre class = snippet-code-html lang-html prettyprint-override> < div class = carousel>< div id = x> x< / div>< div id = y> y< / div>< div id = z> z< / div>< / div>



效果很好;如果您使用触控板或手指滚动轮播,它会捕捉到每个项目。



我要添加的内容是指标。例如在Bootstrap中,这些小点或线表示转盘中有多个物件,转盘中的每个项目都有一个指示器,突出显示了当前项目。单击指示符通常会将您滚动到指定的项目。





我需要这个吗? (我假设是这样。)我应该如何检测当前可见的项目?

解决方案

在现代浏览器中处理此问题的方法是与 IntersectionObserver 。在下面的示例中, IntersectionObserver 会在子元素之一超过50%阈值时触发其回调,从而使该元素具有最大的 intersectionRatio 。发生这种情况时,我们会根据当前所选项目的索引重新呈现该指标。



请注意,Safari在实现对<$ c $的支持时有点晚了c> IntersectionObserver 。 IntersectionObserver刚在Safari 12.1中可用。您可以使用以下脚本标记,使用 IntersectionObserver polyfill 支持较旧的浏览器: / p>

 < script src = https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver> ;< / script> 

奖金提示:您可以使用滚动行为:平滑以动画化 scrollIntoView 调用。



  var轮播= document.querySelector('。carousel'); var指标= document.querySelector('#indicator'); var元素= document.querySelectorAll('。carousel> *'); var currentIndex = 0; function renderIndicator(){//这只是一个示例指标;您可能可以做更好的指标。innerHTML=’’; for(var i = 0; i< elements.length; i ++){var button = document.createElement(’button’); button.innerHTML =(i === currentIndex?‘u2022’:‘u25e6’); (function(i){button.onclick = function(){elements [i] .scrollIntoView();}})(i); indicator.appendChild(button); }} var观察者=新的IntersectionObserver(函数(条目,观察者){//查找具有最大交叉比率的条目var Activated = entry.reduce(函数(max,entry){返回(entry.intersectionRatio&max.intersectionRatio) ?entry:max;}); if(activated.intersectionRatio> 0){currentIndex = elementIndices [activated.target.getAttribute( id)]; renderIndicator();}},{root:carousel,threshold:0.5} ); var elementIndices = {}; for(var i = 0; i  

 。轮播{滚动快照类型:x必选; -webkit-overflow-scrolling:触摸;宽度:100vw;空白:nowrap;溢出x:滚动;滚动行为:smooth} .carousel> * {display:inline-block; scroll-snap-align:开始;宽度:100vw;高度:80vh;}#x {背景颜色:粉红色;}#y {背景颜色:浅蓝色;}#z {背景颜色:浅灰色;}  

< pre class = snippet-code-html lang-html prettyprint-override> < script src = https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver> ;< / script>< div class = carousel>< div id = x> x< / div>< div id = y> y< / div>< div id = z> z< / div>< / div>< div id = indicator>•◦◦< / div>


I'm building a scrolling carousel using CSS scroll snap.

.carousel {
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  width: 100vw;
  white-space: nowrap;
  overflow-x: scroll;
}

.carousel > * {
  display: inline-block;
  scroll-snap-align: start;
  width: 100vw;
  height: 100vh;
}

#x {
  background-color: pink;
}
#y {
  background-color: lightcyan;
}
#z {
  background-color: lightgray;
}

<div class="carousel">
<div id="x">x</div>
<div id="y">y</div>
<div id="z">z</div>
</div>

It works pretty well; if you scroll the carousel with the trackpad or with a finger, it snaps to each item.

What I'd like to add to this are "indicators." e.g. in Bootstrap, these are little dots or lines indicating that there are multiple things in the carousel, one indicator per item in the carousel, with the current item highlighted. Clicking on an indicator will typically scroll you to the specified item.

Do I need JavaScript for this? (I assume so.) How should I detect which item is currently visible?

解决方案

The way to handle this in modern browsers is with IntersectionObserver. In the below example, the IntersectionObserver fires its callback whenever one of the child elements crosses the 50% threshold, making it the element with the largest intersectionRatio. When this happens, we re-render the indicator based on the index of the currently selected item.

Note that Safari was a bit late in implementing support for IntersectionObserver. IntersectionObserver just became available in Safari 12.1. You can use the IntersectionObserver polyfill to support older browsers, using this script tag:

<script src="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>

Bonus tip: You can use scroll-behavior: smooth to animate the scrollIntoView call.

var carousel = document.querySelector('.carousel');
var indicator = document.querySelector('#indicator');
var elements = document.querySelectorAll('.carousel > *');
var currentIndex = 0;

function renderIndicator() {
  // this is just an example indicator; you can probably do better
  indicator.innerHTML = '';
  for (var i = 0; i < elements.length; i++) {
    var button = document.createElement('button');
    button.innerHTML = (i === currentIndex ? '\u2022' : '\u25e6');
    (function(i) {
      button.onclick = function() {
        elements[i].scrollIntoView();
      }
    })(i);
    indicator.appendChild(button);
  }
}

var observer = new IntersectionObserver(function(entries, observer) {
  // find the entry with the largest intersection ratio
  var activated = entries.reduce(function (max, entry) {
    return (entry.intersectionRatio > max.intersectionRatio) ? entry : max;
  });
  if (activated.intersectionRatio > 0) {
    currentIndex = elementIndices[activated.target.getAttribute("id")];
    renderIndicator();
  }
}, {
  root:carousel, threshold:0.5
});
var elementIndices = {};
for (var i = 0; i < elements.length; i++) {
  elementIndices[elements[i].getAttribute("id")] = i;
  observer.observe(elements[i]);
}

.carousel {
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  width: 100vw;
  white-space: nowrap;
  overflow-x: scroll;
  scroll-behavior: smooth
}

.carousel > * {
  display: inline-block;
  scroll-snap-align: start;
  width: 100vw;
  height: 80vh;
}

#x {
  background-color: pink;
}
#y {
  background-color: lightcyan;
}
#z {
  background-color: lightgray;
}

<script src="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>
<div class="carousel">
<div id="x">x</div>
<div id="y">y</div>
<div id="z">z</div>
</div>
<div id="indicator">• ◦ ◦</div>

这篇关于具有CSS滚动捕捉的指示器(点)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆