30

不可思议,纯 css 都能图片滚动

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzU4MzUzODc3Nw%3D%3D&%3Bmid=2247484192&%3Bidx=1&%3Bsn=907fdd0d4ed0ad61d2c050e484096c63
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

2YZjiaJ.png!mobile

背景

传统的 swiper 太重了,里面封装了很多我们不需要的功能,而一个简单的滚动功能没必要那么重的文件。于是就想着自己如何实现,如何才能用最少的代码最优雅的实现呢?是否可以推翻传统的实现,使用纯 css 的某些特效实现呢?

肯定可以的呀,我就实现了一个基于 scroll-snap-type [1] 属性做的滚动

实现思路

scroll-snap-type:网页容器滚动停止的时候,自动平滑定位到指定元素的指定位置,有点像当子元素滚动到某一个点的时候会被父元素吸附过去,它的目的是让你的页面滚动停留在你希望用户关注的重点区域,利用这个css属性,就可以自动判断用户是要滚到哪

QR7B7nI.gif!mobile

那么问题又来了,这个临界点我们怎么设置呢?css 属性都是相辅相成的,我们可以使用 scroll-snap-align [2] :发生滚动的时候,在一屏内对齐方式,scroll-snap-type 会根据 scroll-snap-align的设置的临界点进行滚动,如果不设置它没有任何效果

nyUJFb.gif!mobile

scroll-snap-align有几个参数,start,center,end,分别感受一下他们之间的区别

scroll-snap-align:start riaeuum.gif!mobile       

scroll-snap-align:center VBjYfaz.gif!mobile

scroll-snap-align:end yUnyeeA.gif!mobile

平滑定位到指定元素的指定位置的效果实现了;滚动最关键最重要的一步,就是如何让元素平滑缓慢的滚动呢?这时候 scroll-behavior [3] 派上用场了,它的目的是滚动的时候自带动效一点都不生硬,作为用户的我体验极好

没有用的时候

YrEZfiA.gif!mobile

使用了之后

M32I7fR.gif!mobile

对比效果还是很明显的

把上面提到的三个属性放在一起就实现了平稳缓慢的滚动,再借助js移动位置我们的自动轮播滚动就完美的实现了。

// css
.swiper-box {
scroll-behavior: smooth;
scroll-snap-type: x mandatory;
}
.swiper-image {
scroll-snap-align: start;
}
// js
setInterval(function () {
var clientWidth = ele.clientWidth;
var index = Math.floor(ele.scrollLeft / clientWidth) + 1;
if (index > imageList.length - 1) {
index = 0;
}
eleSwiperBox.scrollLeft = clientWidth * index + _ele.offsetLeft * index;
}, 3000)

就是这么简单,几行代码就实现了滚动自动轮播。如上面所说用最少的代码最优雅 就这样高高兴兴的结束了么?别急,投入项目使用要再看看浏览器的兼容性的,如果兼容性不好的话,很有可能就没法投入到项目中去

eIVRbei.png!mobile

Safari浏览器都不支持,完了完了,不支持就相当于没有,可以是又想用,那就只能写一个 polyfill

我们想想scroll-behavior: smooth; 实现的效果是怎么样的?

aiAbIne.gif!mobile

是滚动的过程中缓慢的滚,有条不紊,按照一定的步长再动,好像在做移动匀速的直线运动

知道了原理就好办了在属性不支持的情况下我们就写一个递归函数,ele.scrollLeft不是一步到位,而是慢慢的每次只滚动一点点,一直到结束。

if (!CSS.supports("scroll-behavior: smooth")) {
var step = function () {
var numScrolDistance = scrollLeft - ele.scrollLeft;
if (Math.abs(numScrolDistance) <= 3) {
ele.scrollLeft = scrollLeft;
} else {
ele.scrollLeft += numScrolDistance / 4;
requestAnimationFrame(step);
}
};
step();
} else {
ele.scrollLeft = scrollLeft;
}

用js写了一个ployfill,我们的兼容性问题就解决了。组合css的几个属性我们的自动轮播滚动效果就实现了,代码很简单,主要是可以使用尝试新的用不一样css解决方案。

iMJneq2.gif!mobile

不仅仅只有轮播滚动

如果我们不做轮播滚动,做点击缓慢滚动也是很方便很好使用的属性。

VB7vea2.gif!mobile

像这种情况也是很好使用的。之前在项目中就遇见过这种需求,实现了效果比较生硬,代码也不优雅,后来有了 css 大佬坐镇指点 [4] ,用的css属性结合递归的实现,特别有意思

代码封装一下

把上面的代码稍微封装一下,写成一个组件,在我们的在项目中就可以随意使用了,一次封装终身享用。都是原生的实现,没有框架的限制,有兼容性的处理。还附带了图片懒加载和异常处理

代码封装 [5]

1. 可以npm安装使用

npm i snap-swiper

import "snap-swiper/snap-swiper.css";
const snapSwiper = require("snap-swiper");
snapSwiper({
imageList:[],
el,
});

npm 下载使用demo [6]

代码地址 [7]

参考文章

CSS scroll-snap滚动事件停止及元素位置检测 [8]

大侠,请留步,要不过来了解下CSS Scroll Snap? [9]

References

[1] scroll-snap-type:  https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-type

[2] scroll-snap-align:  https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-align

[3] scroll-behavior:  https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior

[4] css 大佬坐镇指点:  https://www.zhangxinxu.com/

[5] 代码封装:  https://github.com/yued-fe/snap-swiper

[6] npm 下载使用demo:  https://codesandbox.io/s/gifted-ives-zco4l?file=/index.html

[7] 代码地址:  https://github.com/yued-fe/snap-swiper

[8] CSS scroll-snap滚动事件停止及元素位置检测:  https://www.zhangxinxu.com/wordpress/2019/04/css-scroll-snap-event-element-detect/

[9] 大侠,请留步,要不过来了解下CSS Scroll Snap?:  https://www.zhangxinxu.com/wordpress/2018/11/know-css-scroll-snap/


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK