【每日技巧】column实现水平翻页和scroll-snap

315 阅读3分钟

1、column实现水平翻页

columns属性: column-width column-count;

1、column-width:列的宽度,auto默认值。表示每一栏的宽度由其它CSS属性决定,例如column-count。不支持负值和百分比。如果设定值比外部容器宽度大,则最终展现宽度为外部容器宽度

2、column-count:一屏显示的列数,auto默认值。表示分栏数目由其它CSS属性决定,例如column-width。不支持负值,也不支持0。column-count与column-width都有可能有更高的优先级,统一转换column-count值,哪个小就使用哪一个。

columns属性: column-gap表示每一栏之间的那个空白间隙大小。

点击查看demo

HTML:

<div class="g-box">
    <div class="book noSelect" id="book">
      <div class="content" id="content">
        <h3>第一章 总纲</h3>
        <p>&emsp;&emsp;中国GCD是中国工人阶级的先锋
        ....
      </div>
    </div>
</div>

CSS:

.g-box{
    margin: 0 auto;
    position: relative;
    width: 600px;
    max-width: 100vw;
    height: 800px;
    overflow: hidden;
    background: #9b822d;

}
.book {
    height: 100%;
    margin: 0 16px;
}
.content {
    width: 100%;
    height: 100%;
    columns: 100vw 1;
    column-gap: 16px;
    transition: all .1s;
}

JS:

const content = document.getElementById('content');
const book = document.getElementById('book');
let startLeft = 0; // 当前拖动位置
let moveStart = false; // 是否进行滑动
const downFun = function (e) {
    startLeft = e.clientX || Math.floor(Number(e.changedTouches[0].clientX));
    moveStart = true; // 开始滑动
};
const moveFun = function (e, ele) {
    if (!moveStart) return;
    ele.style.transform = `translateX(${Number(ele.style.transform.replace(/[^0-9\-,]/g,'')) + (e.clientX || Math.floor(Number(e.changedTouches[0].clientX))) - startLeft}px)`; // 控制content偏移
    startLeft = e.clientX || Math.floor(Number(e.changedTouches[0].clientX));
};
const upFun = function (ele) {
    moveStart = false;
    const nowPos = Number(ele.style.transform.replace(/[^0-9\-,]/g,''));
    if (nowPos > 0) { // 最开始一页
      ele.style.transform = `translateX(0px)`;
    } else if (Math.floor(Math.abs(nowPos) / ele.clientWidth) >= Math.floor(ele.scrollWidth / ele.clientWidth) - 1) { // 最后一页
      ele.style.transform = `translateX(-${ele.scrollWidth - content.clientWidth}px)`;
    } else { // 中间页
      ele.style.transform = `translateX(-${Math.round(Math.abs(nowPos) / ele.clientWidth) * (ele.clientWidth + 16)}px)`;
    }
};
// 电脑端
book.addEventListener('mousedown',function (e) {
    downFun(e);
});
book.addEventListener('mousemove',function (e) {
    moveFun(e, content);
});
document.body.addEventListener('mouseup',function () {
    upFun(content);
});
// 手机端
book.addEventListener('touchstart',function (e) {
    downFun(e);
});
book.addEventListener('touchmove',function (e) {
    moveFun(e, content);
});
document.body.addEventListener('touchend',function () {
    upFun(content);
})

2、scroll-snap

scoll-snap可以使浏览器停止滑动时,如果目标元素在视窗内则自动滑动到目标位置。适用场景:移动端的商品展示,整屏展示定位。

scroll-snap-type: x/y 父元素滑动方向

scroll-snap-align: start/end/center。子元素停止位置 点击查看demo

HTML:

<div id="result" class="result"></div>
  <div id="listY" class="list-ul">
  <div class="list-li active">
    <img class="list-img" src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/3/19/169936a894b4a755~tplv-t2oaga2asx-image.image">
  </div>
  <div class="list-li">
    <img class="list-img" src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/3/19/169936a894b4a755~tplv-t2oaga2asx-image.image">
  </div>
  <div class="list-li">
    <img class="list-img" src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/3/19/169936a894b4a755~tplv-t2oaga2asx-image.image">
  </div>
  <div class="list-li">
    <img class="list-img" src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/3/19/169936a894b4a755~tplv-t2oaga2asx-image.image">
  </div>
</div>

CSS:

.list-ul {
    width: 500px; height: 353px;
    margin: auto;
    font-size: 0;
    scroll-snap-type: y mandatory;
    white-space: nowrap;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    -ms-overflow-style: none; // IE 10+隐藏滚动条
    overflow: -moz-scrollbars-none; // Firefox隐藏滚动条
}
.list-ul::-webkit-scrollbar { width: 0 !important }
.list-li {
    width: 100%; height: 100%;
    scroll-snap-align: center;
    position: relative;
    transition: filter .3s;
}
@media screen and (max-width: 480px) {
.list-ul {
    width: 100%;
    height: calc(100vw / 500 * 353);
}
}
img {
    -webkit-user-drag: none;
    display: block;
    width: 100%;
    height: 100%;
}

JS:

const content = document.getElementById('listY');
const result = document.getElementById('result');
// 定时器,用来检测滚动是否结束
let timerScrollEndDetect = null;
// 滚动事件开始
content.addEventListener('scroll', function () {
    clearTimeout(timerScrollEndDetect);
    timerScrollEndDetect = setTimeout(function () {
      // 100毫秒内滚动事件没触发,认为停止滚动了
      // 对列表元素进行位置检测
      [].slice.call(content.children).forEach(function (eleList, index) {
        if (Math.abs(eleList.getBoundingClientRect().top - content.getBoundingClientRect().top) < 10) {
          // 添加标志类名
          eleList.classList.add('active');
          // 提示
          result.innerHTML = '滚动结束,当前显示的是第'+ (index + 1) +'个列表。';
        } else {
          eleList.classList.remove('active');
        }
      });
    }, 100);
    
    // 提示
    result.innerHTML = '滚动中...';
});