JavaScript练手小技巧:利用鼠标滚轮控制图片轮播

近日,在浏览网站的时候,发现了一个有意思的效果:一个图片轮播,通过上下滚动鼠标滚轮控制图片的上下切换。

于是就有了自己做一个的想法,顺带复习下鼠标滚轮事件。

鼠标滚轮事件,参考这篇文章:鼠标滚轮事件-CSDN博客

一、HTML和CSS

无论怎么样的滚动,首先要制作图片轮播的结构和样式。

HTML:

<div class="box" id="box"><ul class="list" id="list"><li><img src="../images/pic1.jpg" alt=""></li><li><img src="../images/pic2.jpg" alt=""></li><li><img src="../images/pic3.jpg" alt=""></li><li><img src="../images/pic4.jpg" alt=""></li><li><img src="../images/pic5.jpg" alt=""></li></ul>   <div class="dots" id="dots"></div>
</div>

HTML结构很简单,就是一个 div 里面套了两个结构:图片区和控制点区。

  • 图片区 ul#list,就是一个 ul,里面有多个 li 嵌套了图片。
  • 控制点区 div#dots 没有内容,这是因为控制点要根据图片的数量(ul 的 li 个数)动态生成。

CSS:

*{margin: 0;padding: 0;
}
ul,li,ol{list-style: none;
}
.box{width: 600px;height: 399px;border:20px #000 solid;margin-left: auto;margin-right: auto;overflow: hidden;position: relative;margin-top: 100px;
}
.list{position: relative;
}
.list img{display: block;
}
.list li{width: 600px;height: 399px;overflow: hidden;
}
.box .dots{position: absolute;bottom: 20px;left: 50%;transform: translateX(-50%);display: flex;background: rgba(255,255,255,0.5);padding: 5px;border-radius: 30px;
}
.box .dots span{display: block;width: 15px;height: 15px;background: #fff;border-radius: 50%;margin-left: 5px;margin-right: 5px;cursor: pointer;
}
.box .dots span.active{background: #f30;
}

CSS代码如上,就不分析了,反正就这样。强调两点:

  • 整个  div.box 要相对定位,约束绝对定位的控制点区 div#dots
  • ul.list 也要相对定位,因为要复制第一个图,放到最后;复制最后一个图,放到第一图的前面。复制出来的图都是绝对定位的。

二、JS

1. 为了防止重复执行滚动事件,写一个 flag,当为 true 的时候,就不执行滚动事件。默认值为 false。

let isScroll = false;

2. 根据图片的个数动态生成点(span)。为了防止过度操作 DOM,使用了  createDocumentFragment 缓存生成的span 标签。

let li = list.querySelectorAll("li");
let li_len = li.length;
let index = 0;
let wrap = document.createDocumentFragment();
// 初始化工作
for(let i = 0; i < li_len; i++){let span = document.createElement("span");span.dataset.index = i;if(i == 0){span.classList.add("active");}wrap.appendChild(span);span.addEventListener("click",function(){index = this.dataset.index;changePic(index);} );
}
dots.appendChild(wrap);

3. 上下移动图片,就是在控制图片的 transform 的 translateY 属性。

// 图片切换函数:index++
function nextPic(){index++;if( index >= li_len ){index = 0;list.style.transform = "translateY(399px)"; // 调整list位置document.body.offsetHeight; // 强制重绘HTML}changePic(index);
}// 图片切换函数:index--
function prevPic(){index--;if( index < 0 ){index = li_len - 1;list.style.transform = "translateY(" + (-399*li_len) + "px)";document.body.offsetHeight; // 强制重绘HTML}changePic(index);
}

 4. 切换图片,就是在换图,已经更改控制点的样式。

// 切换图片
function changePic(index){// 点的切换let dotsBros = findeBros(dots_span[index]);dots_span[index].classList.add("active");dotsBros.forEach(function(item){item.classList.remove("active");});// 图片切换isScroll = true;list.style.transform = "translateY(" + (-index * 399) + "px)";list.style.transition = "transform 0.5s";document.body.offsetHeight; // 强制重绘HTML
}

5. 当动画结束的时候,就要恢复 flag 变量的值为 flase,并且去掉图片的过渡动画。

// 动画结束时,恢复初始状态
list.addEventListener("transitionend",function(){isScroll = false;list.style.transition = "none";});

6. 滚动事件,判断滚轮值的正负,选择上还是下滚动图片。

// 鼠标滚轮事件
box.addEventListener("wheel",function(e){e.preventDefault();let delta = e.deltaY;if(delta > 0 && isScroll == false ){nextPic();}else if(delta < 0 && isScroll == false){prevPic();}
},{passive: false
});

 完整JS代码:

let box = document.getElementById("box");
let list = document.getElementById("list");
let dots = document.getElementById("dots");
let isScroll = false;let li = list.querySelectorAll("li");
let li_len = li.length;
let index = 0;
let wrap = document.createDocumentFragment();
// 初始化工作
for(let i = 0; i < li_len; i++){let span = document.createElement("span");span.dataset.index = i;if(i == 0){span.classList.add("active");}wrap.appendChild(span);span.addEventListener("click",function(){index = this.dataset.index;changePic(index);} );
}
dots.appendChild(wrap);
let dots_span = dots.children;
// 初始图片
let liFirst = li[0];
let liLast = li[li_len - 1];
let newLiFirst = liFirst.cloneNode(true);
let newLiLast = liLast.cloneNode(true);
list.appendChild(newLiFirst);
list.appendChild(newLiLast);
newLiLast.style.position = "absolute";
newLiLast.style.top = "-399px";
newLiLast.style.left = "0";
// 工具函数:获取兄弟节点
function findeBros(tag){let bros = [];let parent = tag.parentNode;for(let i = 0; i < parent.children.length; i++){if(parent.children[i] !== tag){bros.push(parent.children[i]);}}return bros;
}
// 图片切换函数:index++
function nextPic(){index++;if( index >= li_len ){index = 0;list.style.transform = "translateY(399px)"; // 调整list位置document.body.offsetHeight; // 强制重绘HTML}changePic(index);
}// 图片切换函数:index--function prevPic(){index--;if( index < 0 ){index = li_len - 1;list.style.transform = "translateY(" + (-399*li_len) + "px)";document.body.offsetHeight; // 强制重绘HTML}changePic(index);
}// 切换图片
function changePic(index){// 点的切换let dotsBros = findeBros(dots_span[index]);dots_span[index].classList.add("active");dotsBros.forEach(function(item){item.classList.remove("active");});// 图片切换isScroll = true;list.style.transform = "translateY(" + (-index * 399) + "px)";list.style.transition = "transform 0.5s";document.body.offsetHeight; // 强制重绘HTML
}
// 动画结束时,恢复初始状态
list.addEventListener("transitionend",function(){isScroll = false;list.style.transition = "none";
});// 鼠标滚轮事件
box.addEventListener("wheel",function(e){e.preventDefault();let delta = e.deltaY;if(delta > 0 && isScroll == false ){nextPic();}else if(delta < 0 && isScroll == false){prevPic();}
},{passive: false
});

                                                                                                                                                                                                                                                                                                                                                                                                                                                                            

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

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

相关文章

Vue如何将网页转换成图片或PDF并上传

一.使用html2canvas获取页面元素并绘制成图片 htmlcanvas中文文档 npm install --save html2canvas<template><div><button click"uploadImg">上传</button><div ref"yourDom"><!-- ...图片中页面内容 --><img s…

【Linux】多线程:线程互斥、互斥锁

目录 一、多线程访问公共资源时所产生的问题 二、互斥相关背景概念 互斥量mutex&#xff08;锁&#xff09;的引入 三、互斥量 1、初始化互斥量&#xff08;mutex&#xff09; 2、互斥量加锁 3、互斥量解锁 4、 销毁互斥量 四、互斥量的使用 1、使用静态互斥量 2、…

安泰功率放大器在微纳光固化3D打印中的具体应用

随着科技的进步&#xff0c;3D打印技术已经渗透到各个领域&#xff0c;尤其是微纳光固化3D打印技术。这种技术结合了光学、材料科学和微电子学的知识&#xff0c;能够制造出具有微米级精度的复杂物体。本文Aigtek安泰电子将带你探索功率放大器在微纳光固化3D打印中的应用&#…

OpenCV 之 模版匹配多个对象、图片旋转 综合应用

引言 在图像处理和计算机视觉中&#xff0c;模板匹配是一种常用的技术&#xff0c;用于在一幅较大的图像中查找与给定模板图像相似的部分。然而&#xff0c;在实际应用中&#xff0c;目标物体可能会出现在不同的角度&#xff0c;这就需要我们在匹配之前对模板进行旋转处理。本…

仿某皮影狸app官网源码 不错的APP下载官网单页源码 HTML源码

分享一款不错的APP下载官网单页源码&#xff0c;直接修改index.html即可 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/89731228 更多资源下载&#xff1a;关注我。

Python(PyTorch和TensorFlow)图像分割卷积网络导图(生物医学)

&#x1f3af;要点 语义分割图像三层分割椭圆图像脑肿瘤图像分割动物图像分割皮肤病变分割多模态医学图像多尺度特征生物医学肖像多类和医学分割通用图像分割模板腹部胰腺图像分割分类注意力网络病灶边界分割气胸图像分割 Python生物医学图像卷积网络 该网络由收缩路径和扩…

回归预测 | Matlab基于贝叶斯算法优化XGBoost(BO-XGBoost/Bayes-XGBoost)的数据回归预测+交叉验证

回归预测 | Matlab基于贝叶斯算法优化XGBoost(BO-XGBoost/Bayes-XGBoost)的数据回归预测交叉验证 目录 回归预测 | Matlab基于贝叶斯算法优化XGBoost(BO-XGBoost/Bayes-XGBoost)的数据回归预测交叉验证效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab实现基于贝叶…

AI大模型精准升级!揭秘高级RAG架构,让回答更精准、更可靠!

什么是 RAG&#xff1f; 当然&#xff0c;本文依然会讲解一部分 RAG 的基础知识&#xff0c;让你能够对文章的上下文有个初步了解。 “检索增强生成” (Retrieval Augmented Generation)&#xff0c;简称 RAG&#xff0c;这一概念首次出现在 2020 年 Meta 发布的一项学术研究…

中国《人工智能安全治理框架》1.0版正式发布 规范各类AI、算法

今日&#xff0c;全国网络安全标准化技术委员会发布《人工智能安全治理框架》1.0版。《框架》提出了包容审慎、确保安全&#xff0c;风险导向、敏捷治理&#xff0c;技管结合、协同应对&#xff0c;开放合作、共治共享等人工智能安全治理的原则。 针对模型算法安全、数据安全和…

RK3576芯片在智能家居里中型智慧屏产品的应用方案分析

智能家居在近年来得到了快速发展&#xff0c;AI技术不断发展&#xff0c;人机交互十分成熟&#xff0c;各种家电也都迎来了智能化浪潮&#xff0c;智能家居为人们提供了优秀的产品体验&#xff0c;受到主流消费者的青睐&#xff0c;智能家居里的中型智慧屏产品也随之兴起。 瑞芯…

RedisTemplate操作String的API

文章目录 1 String 介绍2 命令3 对应 RedisTemplate API❄️❄️ 3.1 添加缓存❄️❄️ 3.2 设置过期时间(单独设置)❄️❄️ 3.3 获取缓存值❄️❄️ 3.4 删除key❄️❄️ 3.5 顺序递增❄️❄️ 3.6 顺序递减 ⛄4 以下是一些常用的API⛄5 应用场景 1 String 介绍 String 类型…

anaconda启动jupyter notebook

1.在Windows搜索框搜索anaconda prompt点击打开 2.然后输入命令jupyter notebook 3.在这个页面编写你的程序

MATLAB实现PID参数自动整定

目录 1、项目说明 2、文件说明 1、项目说明 本项目旨在通过 MATLAB 语言实现 PID 参数的自动整定&#xff0c;并设计了一个直观易用的 GUI 界面。该系统特别适用于实验室环境下的 PID 参数自整定任务。整定的核心原则在于优化系统性能&#xff0c;使系统的衰减比尽可能接近理…

2025考公最新视频免费分享花生十三、齐麟、葛欣、阿里木江、龙飞、袁东、飞扬、李梦娇等

&#x1f389;备战公考不用愁&#xff0c;我的小程序为你助力&#x1f389; 这里汇聚了花生十三、齐麟、葛欣、阿里木江、龙飞、彬彬、袁东、飞扬、李梦娇、高照等几十位公考名师。他们的视频课程精彩纷呈&#xff0c;搭配详细讲义&#xff0c;让你轻松掌握公考要点。 作为一…

Java | Leetcode Java题解之第395题至少有K个重复字符的最长子串

题目&#xff1a; 题解&#xff1a; class Solution {public int longestSubstring(String s, int k) {int ret 0;int n s.length();for (int t 1; t < 26; t) {int l 0, r 0;int[] cnt new int[26];int tot 0;int less 0;while (r < n) {cnt[s.charAt(r) - a];…

自然语言处理系列六十一》分布式深度学习实战》TensorFlow深度学习框架

注&#xff1a;此文章内容均节选自充电了么创始人&#xff0c;CEO兼CTO陈敬雷老师的新书《自然语言处理原理与实战》&#xff08;人工智能科学与技术丛书&#xff09;【陈敬雷编著】【清华大学出版社】 文章目录 自然语言处理系列六十一分布式深度学习实战》TensorFlow深度学习…

SpringBoot2:请求处理原理分析-接口参数的常用注解

1、PathVariable 作用说明&#xff1a;获取路径参数 案例&#xff1a; 接口收参形式&#xff1a; GetMapping("/car/{id}/owner/{username}")public Map<String,Object> getCar(PathVariable("id") Integer id,PathVariable("username")…

【uml】graph_legend中的类图怎么看

上图中的方框具有以下含义&#xff1a; 实心灰色方框表示生成图表的结构或类。 带黑色边框的方框表示已记录的结构或类。 带灰色边框的方框表示未记录的结构或类。 带红色边框的方框表示未显示所有继承/包含关系的已记录的结构或类。如果图表不适合指定的边界&#xff0c;则图…

雷电9模拟器安装magisk和lsposed

模拟器环境配置 1、开启root 2、开启System.vmdk可写入 安装magisk 1、新建模拟器、开启root权限、并安装debug版magisk 下载地址去上面吾爱论坛作者文章下载吧&#xff01;支持他一下&#xff01; 2、打开magisk的app&#xff0c;点击安装 如果弹出获取权限&#xff0c;直接…

《A Few Useful Things to Know about Machine Learning》论文导读

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl机器学习作为人工智能领域的重要分支,近年来得到了广泛的关注和应用。Pedro Domingos的经典论文《A Few Useful Things to Know about Machine Learning》为我们提供了对机器学习深入且全面的理解…