记录--巧用 overflow-scroll 实现丝滑轮播图
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
前言: 近期我在项目中就接到了一个完成轮播图组件的需求。最开始我也像大家一样,直接选择使用了知名的开源项目 "Swiper",但是后来发现它在移动端项目中某些测试环境下会白屏一段时间。无论如何调试都不能修复这个问题,于是就自己上手写了个轮播图组件,实现代码其实也只有 200 行,很少但是完美解决了我们项目的问题。
虽然已经 2023 年了,但是轮播图组件的实现仍然是考验前端基本功的经久不衰的题目,于是来分享一下实现思路。
tips: 本文主要目的不是一上来就贴代码,而是会一步一步带你理清细节部分,即使你现在没有轮播图这个需求。
一. 使用 overflow-scroll 完成基础框架
大家在项目中肯定接触到溢出滚动的需求,其实就是用到了 overflow-auto 等相关属性。
注意:样式方面,在这里我使用的是
UnoCSS
,将样式內联在了标签里,如果你还不了解这种写法,你可以点击下方的文章学习。不过即使你之前从未了解过UnoCSS
,也不会影响你下面的阅读,因为样式不是本文的重点,并不影响整体阅读。
手把手教你如何创建一个代码仓库让我们快速制造一个溢出的场景来完成准备工作。其实非常简单,就是简单的创造一个容器,容器里放着三个和容器宽高相同的 div。然后给父容器一个 overflow-auto 属性,让它可以在内容溢出的时候发生滚动。
效果如下:
二. 实现合适位置自动切换
现在我们仅仅实现了一个可以滚动的容器而已,但是轮播图最主要的事情就是用户滚动的位置不合适,那么我们也要自动调整到合适的位置显示。
更具体来讲,就是当我们拖动图片到了中间这样的位置松手时,轮播图最重要一个功能就是可以自动切换到上一张或者下一张,准确的显示合适的内容给用户。(因为展示内容区域展示一半一半的内容毫无意义嘛。)
这里就需要用到两个至关重要的 CSS 属性,
- snap-type
- snap-align
我们先看 snap 这个单词的意思。在这里它的意思我认为 “咔嚓一声,折断” 更符合这个属性的含义,不要着急,你可以暂时先带着这个模糊的概念来慢慢理解接下来的内容。
我们先看 snap-type 是用来干什么的。
这里 MDN 的解释不是特别好懂,接下来我会用人话翻译一下它想表达的含义。回到我们的代码部分,我们创建了一个容器 div,并且这个容器因为溢出,并且设置了 overflow-滚动 相关属性。
其实我们的 scroll-type 是用来给滚动容器的!这里特别注意,它一定是用在设置了 overflow-auto 等属性的那个元素上的。关于属性值,我们采用 snap-type: x mandatory。
在这里x
的含义代表着横轴发生的滚动,那么聪明的你可以猜到,它也有一个y
属性,代表着竖轴发生滚动时的设置。这里还有一个关键字
mandatory
代表着强制的意思。因为在某些情况下,浏览器会认为用户滑到下面这种位置是自愿的,但是我们的场景是不需要考虑这种情况的,所以要告诉浏览器我们需要你帮我 “强制咔嚓折断”。
至于 proximity ,这个属性的算法有点奇怪,我也没太搞懂它的含义,不过我们的需求不需要用到这个关键字,大家有兴趣也可以自行查阅。
接下来给我们的容器设置这个属性,让我们先看看效果。
什么情况?怎么没效果呢?目前为止我们仅仅给容器设置了滚动的需求还是不够的,还得告诉子元素滚动到什么位置停下才行。这里就需要用到
snap-align
属性了。它是给滚动容器的子元素设置的。snap-align
,这个属性有三个值可以设置,none
,center
和end
。
其实从这个属性的名字就可以猜到,它其实设置的是子元素的位置是相对于滚动容器的左边对齐还是右边对齐。怎么理解呢?我们将滚动容器的宽度调大,让它可以漏出一点点其它元素的内容。并且只给数字2的元素设置 scroll-align 相关属性。(tips: 这里需要重点注意,我们只给了一个元素设置了这个属性,另外两个元素是没有设置这个属性的。)
snpa-align: start (元素2无论如何都会在松开鼠标的时候紧贴着滚动容的左边,也就是滚动容器的 start 位置
snap-align: center (元素2无论如何都会紧贴着滚动容器中间位置
snap-align: end (元素2的右边无论如何都会紧贴着滚动容器
知道了这三个属性的区别,那么接下来复原我们的容器样子,因为我们实际上轮播图的每一项的宽高和滚动容器的内容区是恰好相等的,所以我们给子元素无论设置怎样的三个值的效果都是一样的。
让我们看一下效果:
看起来效果还不错~
三. 实现上一项和下一项切换功能
我们准备两个按钮,当用户点击这两个按钮的时候,可以进行手动的切换上一张和下一张。
这里我们需要用到滚动容器的 scroll 事件,需要给滚动容器绑定相对的回调函数。
这里通过e.target
就可以拿到我们滚动容器本身。容器自身存在一个 scollLeft 属性,你需要知道一个知识点其实发生滚动的本质就是 scrollLeft 值的变化。
注意观看下面滚动容器的 scrollLeft 属性值的变化。
知道了这个关键点,那么我们的
pre
和next
函数就可以很明确的书写了。
首先通过 ref 拿到元素本身。
然后在
pre
函数内部获取当前滚动元素的scollLeft
值。
紧接着,你需要知道的是,这个值即是一个可读属性,也是一个可写属性。那么我们就可以进行判断,如果当前照片不是第一张的话。,那么我就让 scrollLeft 的值 -300。这里有两个关键的知识点。
- 第一张对应的 scrollLeft 等于0
- 这里的 300 是我们写死的宽度,你可以根据后面自己的项目优化这个值。
让我们看一下效果,先让我们手动滚动到第三张,然后点击上一张切换。
这里好像有一点点不对劲,我们不是平缓过度到上一张的而是直接切换到上一张的,这里很简单,需要给滚动容器设置一个
scroll-behavior:smooth
即可。
我们看一下效果:
下一张按钮的实现同理,这里不过多赘述,代码如下:
最终的效果:
四. 源码
<script setup lang="ts">
import { ref, computed } from "vue"; const box = [
{
number: 1,
bg: "blue",
}, {
number: 2,
bg: "pink",
}, {
number: 3,
bg: "red",
},
]; const containerEl = ref<HTMLDivElement>(); function scrollEvent(e: UIEvent) {
const containerEl = e.target as HTMLDivElement;
} // 上一张
function pre() {
const el = containerEl.value;
if (!el) return; const scrollLeft = el?.scrollLeft; if (scrollLeft > 0) {
el.scrollLeft = scrollLeft - 300;
}
} function next() {
const el = containerEl.value;
if (!el) return; const scrollLeft = el?.scrollLeft; const max = (box.length - 1) * 300; //轮播图的数量 -1 if (scrollLeft < max) {
el.scrollLeft = scrollLeft + 300;
}
}
</script> <template>
<div
class="w-100vw h-100vh text-14px text-black flex justify-center items-center"
>
<div
@click.stop="pre"
class="w-60px h-60px rounded-full bg-black flex items-center justify-center"
>
<span class="text-white">上一张</span>
</div> <div
ref="containerEl"
@scroll="scrollEvent"
class="w-300px h-300px overflow-auto flex snap-x snap-mandatory scroll-smooth"
>
<div
v-for="(item, index) in box"
class="w-300px h-300px shrink-0 leading-300px text-center snap-center"
:style="{ backgroundColor: item.bg }"
>
<span class="text-100px text-white">{{ item.number }}</span>
</div>
</div> <div
@click="next"
class="w-60px h-60px rounded-full bg-black flex items-center justify-center"
>
<span class="text-white">下一张</span>
</div>
</div>
</template>
本文转载于:
https://juejin.cn/post/7248655627927601207
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
记录--巧用 overflow-scroll 实现丝滑轮播图的更多相关文章
- 记录一下自己用jQuery写的轮播图
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- [转] 设置div的overflow:scroll,但是在手机上滑动的时候有点卡顿
设置div的overflow:scroll,但是在手机上滑动的时候有点卡顿,所以在这个div上加一个css: -webkit-overflow-scrolling : touch; 在苹果手机上使用- ...
- CSS中overflow:scroll怎么设置只上下滚动而不左右滚动
CSS中"overflow:scroll"默认是左右,上下都滚动.怎么设置只上下滚动而不左右滚动,下面有个不错的解决方法 CSS中"overflow:scroll&quo ...
- iScroll框架解析——Android 设备页面内 div(容器,非页面)overflow:scroll; 失效解决(转)
移动平台的活,兼容问题超多,今儿又遇到一个.客户要求在弹出层容器内显示内容,但内容条数过多,容器显示滚动条.按说是So easy,容器设死宽.高,CSS加属性 overflow:scroll; -we ...
- 通过overflow: scroll;来实现部分区域的滚动
在移动端中,我们希望元素的滚动,可以通过一些插件的使用来实现滚动,当然也可以自己来实现. 比如:对于某一个区域,我们可以限制好高度之后,设定:overflow-y: scroll; 这样,就可以实现滚 ...
- overflow:scroll 滚动条不显示
overflow:scroll 滚动条不显示 ::-webkit-scrollbar-thumb 可能因为 自定义的滚动条height比元素可展示内容大
- 解决页面使用overflow: scroll,overflow-y:hidden在iOS上滑动卡顿的问题
解决页面使用overflow: scroll,overflow-y:hidden在iOS上滑动卡顿的问题 div{ width: 100%; overflow-y: hidden; -webkit-o ...
- ios下使用overflow scroll情况下,到达最极端的情况时会拖动整个页面的解决办法
今天开发ipad webapp时,遇到个问题就是在支持内部滚动(overflow:scroll)的页面中,在滚到到最极端(最上或者最下时),会拖动整个页面,带来不好的用户体验. 方法一,从网上找到的: ...
- 内层元素设置position:relative后父元素overflow:hidden overflow:scroll失效 解决方法
内层元素设置position:relative后父元素overflow:hidden overflow:scroll 都失效 解决方法:在position:relative的外层父容器加positio ...
- 父元素设置固定宽度并设置overflow:scroll,如何让子元素撑开父元素
<div class="a"> <div class="b"> <div class="c">内容内容, ...
随机推荐
- Pandas处理股票数据
import tushare as ts import pandas as pd # 下载茅台所有股票交易数据 # df = ts.get_k_data(code="600519" ...
- Ubuntu安装typecho博客
Ubuntu安装typecho博客 简介 名称的来历 Typecho 是由 type 和 echo 两个词合成的,来自于开发团队的头脑风暴. Type,有打字的意思,博客这个东西,正是一个让我们通过打 ...
- NC50381 道路和航线
题目链接 题目 题目描述 FarmerJohn正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇,编号为1到T.这些城镇之间通过R条道路(编号为1到R)和P条航线(编号为1到P)连 ...
- Laravel入坑指南(2)——路由、控制器
接上一节,我们已经把Laravel有Hello World项目跑起来了. 现在各位小友最着急的,应该是想了解,我们怎么在"页面"echo一个自己的Hello World字符串. & ...
- RunnerGo低代码测试体验
RunnerGo是基于go语言自研的一款企业级全栈式测试平台,采用Apache-2.0 license开源协议,涵盖接口测试.性能测试.UI测试和项目管理等功能,并独创"拖拉拽"的 ...
- Flutter——安装依赖包时,出现Waiting for another flutter command to release the startup lock
问题描述 运行 flutter packages get 时 出现 Waiting for another flutter command to release the startup lock 解决 ...
- windows下的批处理bat文件和Linux下的shell文件的含义
原文:https://www.cnblogs.com/caiguodong/p/10308255.html shell(Linux.Solaris) bat(windows) 含义 # rem 注释行 ...
- 【Filament】立方体贴图(6张图)
1 前言 本文通过一个立方体贴图的例子,讲解三维纹理贴图(子网格贴图)的应用,案例中使用 6 张不同的图片给立方体贴图,图片如下. 读者如果对 Filament 不太熟悉,请回顾以下内容. F ...
- 连接 AI,NebulaGraph Python ORM 项目 Carina 简化 Web 开发
作者:Steam & Hao 本文整理自社区第 7 期会议中 13'21″ 到 44'11″ 的 Python ORM 的分享,视频见 https://www.bilibili.com/vid ...
- 文心一言 VS 讯飞星火 VS chatgpt (207)-- 算法导论15.4 4题
四.说明如何只使用表 c 中 2*min(m,n) 个表项及O(1)的额外空间来计算LCS的长度.然后说明如何只用 min(m,n) 个表项及O(1)的额外空间完成相同的工作.要写代码的时候,请用go ...