巧用 overflow-scroll 实现丝滑轮播图

news2024/12/23 0:13:06

前言:
近期我在项目中就接到了一个完成轮播图组件的需求。最开始我也像大家一样,直接选择使用了知名的开源项目 “Swiper”,但是后来发现它在移动端项目中某些测试环境下会白屏一段时间。无论如何调试都不能修复这个问题,于是就自己上手写了个轮播图组件,实现代码其实也只有 200 行,很少但是完美解决了我们项目的问题。

虽然已经 2023 年了,但是轮播图组件的实现仍然是考验前端基本功的经久不衰的题目,于是来分享一下实现思路。🎁

tips: 本文主要目的不是一上来就贴代码,而是会一步一步带你理清细节部分,即使你现在没有轮播图这个需求。

一. 使用 overflow-scroll 完成基础框架

  1. 大家在项目中肯定接触到溢出滚动的需求,其实就是用到了 overflow-auto 等相关属性。
    image.png

  2. 注意:样式方面,在这里我使用的是 UnoCSS ,将样式內联在了标签里,如果你还不了解这种写法,你可以点击下方的文章学习。不过即使你之前从未了解过 UnoCSS ,也不会影响你下面的阅读,因为样式不是本文的重点,并不影响整体阅读。
    🫱手把手教你如何创建一个代码仓库

  3. 让我们快速制造一个溢出的场景来完成准备工作。其实非常简单,就是简单的创造一个容器,容器里放着三个和容器宽高相同的 div。然后给父容器一个 overflow-auto 属性,让它可以在内容溢出的时候发生滚动。
    image.png
    效果如下:
    1.gif

二. 实现合适位置自动切换

  1. 现在我们仅仅实现了一个可以滚动的容器而已,但是轮播图最主要的事情就是用户滚动的位置不合适,那么我们也要自动调整到合适的位置显示。

  2. 更具体来讲,就是当我们拖动图片到了中间这样的位置松手时,轮播图最重要一个功能就是可以自动切换到上一张或者下一张,准确的显示合适的内容给用户。(因为展示内容区域展示一半一半的内容毫无意义嘛。)
    image.png

  3. 这里就需要用到两个至关重要的 CSS 属性,

    • snap-type
    • snap-align

    我们先看 snap 这个单词的意思。在这里它的意思我认为 “咔嚓一声,折断” 更符合这个属性的含义,不要着急,你可以暂时先带着这个模糊的概念来慢慢理解接下来的内容。
    image.png

  4. 我们先看 snap-type 是用来干什么的。
    image.png
    这里 MDN 的解释不是特别好懂,接下来我会用人话翻译一下它想表达的含义。

  5. 回到我们的代码部分,我们创建了一个容器 div,并且这个容器因为溢出,并且设置了 overflow-滚动 相关属性。
    image.png
    其实我们的 scroll-type 是用来给滚动容器的!这里特别注意,它一定是用在设置了 overflow-auto 等属性的那个元素上的。

  6. 关于属性值,我们采用 snap-type: x mandatory
    image.png
    在这里 x 的含义代表着横轴发生的滚动,那么聪明的你可以猜到,它也有一个 y 属性,代表着竖轴发生滚动时的设置。

  7. 这里还有一个关键字 mandatory 代表着强制的意思。因为在某些情况下,浏览器会认为用户滑到下面这种位置是自愿的,但是我们的场景是不需要考虑这种情况的,所以要告诉浏览器我们需要你帮我 “强制咔嚓折断”
    image.png

  8. 至于 proximity ,这个属性的算法有点奇怪,我也没太搞懂它的含义,不过我们的需求不需要用到这个关键字,大家有兴趣也可以自行查阅。

  9. 接下来给我们的容器设置这个属性,让我们先看看效果。
    image.png
    2.gif

  10. 什么情况?怎么没效果呢?目前为止我们仅仅给容器设置了滚动的需求还是不够的,还得告诉子元素滚动到什么位置停下才行。这里就需要用到 snap-align 属性了。它是给滚动容器的子元素设置的。

  11. snap-align ,这个属性有三个值可以设置,nonecenterend
    image.png
    其实从这个属性的名字就可以猜到,它其实设置的是子元素的位置是相对于滚动容器的左边对齐还是右边对齐。

  12. 怎么理解呢?我们将滚动容器的宽度调大,让它可以漏出一点点其它元素的内容。并且只给数字2的元素设置 scroll-align 相关属性。(tips: 这里需要重点注意,我们只给了一个元素设置了这个属性,另外两个元素是没有设置这个属性的。)

    • snpa-align: start (元素2无论如何都会在松开鼠标的时候紧贴着滚动容的左边,也就是滚动容器的 start 位置
      start.gif

    • snap-align: center (元素2无论如何都会紧贴着滚动容器中间位置
      center.gif

    • snap-align: end (元素2的右边无论如何都会紧贴着滚动容器
      end.gif

  13. 知道了这三个属性的区别,那么接下来复原我们的容器样子,因为我们实际上轮播图的每一项的宽高和滚动容器的内容区是恰好相等的,所以我们给子元素无论设置怎样的三个值的效果都是一样的。
    image.png
    让我们看一下效果:
    4.gif
    看起来效果还不错~

三. 实现上一项和下一项切换功能

  1. 我们准备两个按钮,当用户点击这两个按钮的时候,可以进行手动的切换上一张和下一张。
    image.png

  2. 这里我们需要用到滚动容器的 scroll 事件,需要给滚动容器绑定相对的回调函数。
    image.png
    这里通过 e.target 就可以拿到我们滚动容器本身。容器自身存在一个 scollLeft 属性,你需要知道一个知识点其实发生滚动的本质就是 scrollLeft 值的变化
    image.png
    注意观看下面滚动容器的 scrollLeft 属性值的变化。
    scroll.gif

  3. 知道了这个关键点,那么我们的 prenext 函数就可以很明确的书写了。
    首先通过 ref 拿到元素本身。
    image.png

  4. 然后在 pre 函数内部获取当前滚动元素的 scollLeft 值。
    image.png

  5. 紧接着,你需要知道的是,这个值即是一个可读属性,也是一个可写属性。那么我们就可以进行判断,如果当前照片不是第一张的话。,那么我就让 scrollLeft 的值 -300。这里有两个关键的知识点。

      1. 第一张对应的 scrollLeft 等于0
      1. 这里的 300 是我们写死的宽度,你可以根据后面自己的项目优化这个值。

    image.png

  6. 让我们看一下效果,先让我们手动滚动到第三张,然后点击上一张切换。
    5.gif

  7. 这里好像有一点点不对劲,我们不是平缓过度到上一张的而是直接切换到上一张的,这里很简单,需要给滚动容器设置一个 scroll-behavior:smooth 即可。
    image.png
    我们看一下效果:
    6.gif

  8. 下一张按钮的实现同理,这里不过多赘述,代码如下:
    image.png

  9. 最终的效果:
    7.gif

四. 源码

<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>

五. 结语

在真正的项目上,其实我还实现了从最后一张到第一张,或者从第一张到最后一张的无缝切换,但是讲解起来稍微有点复杂,会让文章变得冗长。所以计划本文只是讲解基础框架,如果有读者希望学习思路的话,我会在之后更新相关知识点🎁。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/687167.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java智慧工厂UWB高精度人员定位管理系统源码

一、系统概述&#xff1a; 智慧工厂高精度定位管理系统源码&#xff0c;采用UWB定位技术&#xff0c;通过部署UWB定位设备实现人、车、物精确定位&#xff0c;打造可寻、可视、可防、可控的一体化管控平台。UWB定位系统具有容量大、稳定性强、精度高、安装便捷、易维护、操作简…

pebblely无需代码连接集简云数据表的方法

1 使用场景 当电商UI接到一个设计产品图的需求时&#xff0c;按照常规的工作安排&#xff0c;从对接需求到最后完成效果图最短时间都要在5天左右&#xff0c;如果遇到高要求的客户&#xff0c;后期还需要在电脑上进一步调整细节&#xff0c;一张成片起码要花上数小时时间去完成…

LabVIEW开发压电陶瓷特性测试系统

LabVIEW开发压电陶瓷特性测试系统 目前&#xff0c;随着科学技术的飞速发展&#xff0c;各个领域都需要纳米级的精密定位系统。而压电定位系统是迄今为止已经得到认可的微纳定位系统。该系统主要由压电驱动系统、位移测量传感器和控制系统组成。其中&#xff0c;整个压电驱动系…

oracle 使用sql语句实现交换一个表中两条记录的某个字段的内容

不要太忙了 好好珍惜眼下 的真爱 &#xff08;马晓静sorry~&#xff09; 表 test --------------- id | i_order --------------- 1 | 22 2 | 23 --------------- 转换后结果为&#xff1a; --------------- id | i_order --------------- 1 | 23 2 | …

【云原生丶Docker】Docker镜像常用命令大全

镜像是Docker中最为核心也是最具创造性的概念&#xff01;在理解Docker的核心概念文章中&#xff0c;我们理解了镜像的含义&#xff0c;下面让我们一起操作一些镜像&#xff0c;包括拉取、推送镜像等操作。 1、镜像支持哪些命令 通过 docker image help 查看 Docker 支持的镜像…

解决nacos频繁输出get changegroupkeys日志

# 1、根据心跳日志&#xff0c;定位日志输出的包名 c.a.n.client.config.impl.ClientWorker : get changedGroupKeys:[]# 2、在 IDEA 中搜索 ClientWorker 所在的包路径 package com.alibaba.nacos.client.config.impl;# 3、在任意格式的配置文件中将该包路径的日志设置为…

Unity 工具 之 Azure OpenAI 功能接入到Unity 中的简单整理

Unity 工具 之 Azure OpenAI 功能接入到Unity 中的简单整理 目录 Unity 工具 之 Azure OpenAI 功能接入到Unity 中的简单整理 一、简单介绍 二、实现原理 三、注意实现 四、简单实现步骤 五、关键代码 六、附加 创建新的 .NET Core &#xff0c;获取 Azure.AI.OpenAI d…

公司个人年终工作总结【10篇】

公司个人年终工作总结1 20__年即将过去&#xff0c;在公司领导的悉心关怀下和同事们的帮助指导下&#xff0c;结合我自身的努力&#xff0c;在工作、学习等各方面都取得了长足的进步&#xff0c;尤其是在保险理赔专业知识和技能培养方面的成熟&#xff0c;使我成为一名合格的车…

Linux_查看硬盘占用情况

一、查看是什么占用了硬盘空间 df -h 这个命令查看的是显示目前在 Linux 系统上的所有文件系统磁盘使用情况&#xff0c;并根据大小适当显示&#xff08;-h 参数代表以可读的方式展示文件的大小&#xff09;。 一下为加 -h 和不加 -h 的结果 不加 -h 加 -h Filesystem&…

探秘安卓广播:揭秘Android广播机制的神奇之处

壹 广播机制 Android中的广播(Broadcast)机制用于进程/线程间通信&#xff0c;该机制使用了观察者模式。观察者模式是一种软件设计模式&#xff0c;该模式是基于消息的发布/订阅事件模型&#xff0c;该模型中的消息发布者是广播机制中的广播发送者&#xff0c;消息订阅者是广播…

ajax原理是什么?如何实现?

一、是什么 AJAX全称(Async Javascript and XML) 即异步的JavaScript 和XML&#xff0c;是一种创建交互式网页应用的网页开发技术&#xff0c;可以在不重新加载整个网页的情况下&#xff0c;与服务器交换数据&#xff0c;并且更新部分网页 Ajax的原理简单来说通过XmlHttpReq…

算法——查找表

查找&#xff0c;根据一个值查找另一个值&#xff0c;value值可以是容器&#xff0c;结构&#xff0c;这样可查找的元素就更多&#xff1b; 哈希冲突&#xff1a; 主关键字&#xff1a;可以唯一的标识一个记录的关键字&#xff0c;如准考证号&#xff1b; 此关键词&#xff…

RFID微图柜的操作流程以及功能介绍

微型图书馆智能书柜是一种基于 RFID 技术的图书自助借阅延伸服务的终端设备&#xff0c;可实现 24 小时无人看守的共享的智能化设备&#xff0c;可自助借还书、自动数据记录分析、自助提醒等一体化管理服务功能。 智能书柜的操作流程 借书&#xff1a;在操作页面上选择“借书…

【好书精读】网络是怎样连接的 —— 信号在网线和集线器中传输

&#xff08; 该图由我使用 AI 绘制 &#xff09; 目录 每个包都是独立传输的 防止网线中的信号衰减很重要 “双绞”是为了抑制噪声 集线器将信号发往所有线路 每个包都是独立传输的 从计算机发送出来的网络包会通过集线器 、 路由器等设备被转发 &#xff0c; 最 终到达…

解决 CentOS/Alma 安装 libpcap-devel 报错:No match for argument: libpcap-devel

环境&#xff1a;Alma 8.5、Centos 7.x 解决方案 Linux 安装软件的时候&#xff0c;需要 libpcap-devel 这个组件&#xff0c;执行命令&#xff1a;yum install libpcap-devel &#xff0c;然后报错如下&#xff1a; Last metadata expiration check: 0:05:24 ago on Mon 12…

5.3 Linux目录配置

5.3.1 Linux目录配置的依据--FHS 根据FHS的标准文件指出&#xff0c;他们的主要目的是希望让使用者可以了解到已安装软件通常放置于那个目录下&#xff0c; 所以他们希望独立的软件开发商、操作系统制作者、以及想要维护系统的使用者&#xff0c;都能够遵循FHS的标准。 也就是…

ECS 简略版说明五:Baking and entity scenes

目录 Baking and entity scenes Creating and editing sub scenes Accessing data in a baker Loading and unloading entity scenes Baking and entity scenes Baking 是一个把 sub scenes 转变成 entity scenes 的过程&#xff0c;使用 bakers和 baking systems: A sub …

数据中心供配电监控系统解决方案介绍 安科瑞 许敏

摘 要&#xff1a;供配电系统始终是数据中心比较重要的内容&#xff0c;在供配电系统能够得到平稳安全的运行的时候&#xff0c;才能够促使数据中心的相关设备具有比较可靠的动力源泉。在新型数据中心不断发展的过程中&#xff0c;其功率密度也相对比较大&#xff0c;对供电的要…

销售人员如何通过CRM系统提升业绩

面对日趋激烈的竞争&#xff0c;销售人员的压力也日益剧增。尤其伴随流量红利的消失&#xff0c;越来越多的企业开始借助数字化工具赋能销售人员&#xff0c;希望通过工具的加持&#xff0c;实现销售人才和销售工具的“人器合一”&#xff0c;最终助力企业业绩的增长。 在市场有…

专访虎牙直播毛茂德 | 看互联网老兵如何用技术驱动效能提升?

引言 作为一位经历了互联网、移动互联网阶段的老兵&#xff0c;毛茂德老师一路走来&#xff0c;始终保持自己的技术初心&#xff0c;不断探索未知领域的宽度&#xff0c;进入虎牙直播后&#xff0c;他积极推动虎牙拥抱云原生&#xff0c;进行业务创新&#xff0c;同时他也发挥技…