问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

详解如何使用原生JS实现移动端web轮播图效果

发布网友 发布时间:2023-07-31 05:49

我来回答

1个回答

热心网友 时间:2023-08-15 00:51


在做移动端开发的时候,必不可少的是轮播图,下面这篇文章主要给大家介绍了关于利用纯JS实现移动端web轮播图的相关资料,重要的是结合Tween算法造轮子,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。
前言
相信大家应该都知道,移动端的轮播图是我们比较常见的需求, 我们最快的实现方式往往是 使用第三方的代码, 例如 swiper , 但当遇到一些比较复杂的轮播图需求时, 往往是束手无策,不知道怎么改.

所以我们要尝试去自己造一些轮子, 以适应各种复杂多变的需求; 另外一点, 自己写的代码如果有bug是很容易修复的, 对自身的提高也很大.
在没有阅读swiper源码的过程下,我尝试自己实现一个简易而不失实用的移动端轮播图, 经过几个小时的思考和实践终于还是实现了(如图):


实现移动端的轮播图要比pc复杂一些,主要表现在以下几个方面:

1.轮播图要适应不同宽度/dpr的屏幕

2.需要使用 touch相关的事件

3.不同机型对 touch事件支持的不太一样,可能会有一些兼容性问题

4.手指移动图片一部分距离,剩下的距离需要自动完成

5.自动完成距离需要有 ease 时间曲线
但编程解决问题的思路都是差不多的,

我们在使用轮播图的时候可以仔细观察,通过现象看到本质:

我们在使用轮播图的时候可以仔细观察,通过现象看到本质:
手指放在图片上, 手指向左或者向右移动, 图片也随之移动;
手指移动的距离少时,图片自动复原位置;手指移动的距离多时,自动切换到下一张;
手指向左或者向右移动的快时,会切换到下一张;
图片轮播是无限循环的, 我们需要采用 3 1 2 3 1的方式来实现, 即 N+2张图来实现N张图的无限循环轮播
我们通过分析现象,可以提出一个基本实现方案:

1. 手指触摸事件可以通过 touchstart touchmove touchend 3个事件来实现

2.在手指 touchstart的时候我们需要记录 手指的x坐标, 可以使用 touch的pageX属性; 还有 这个时间点,

3.手指touchmove的时候我们也需要记录pageX,并且记录累计移动的距离 moveX

4.手指离开的时候,记录时间点, 根据前两步计算的 x方向移动的距离,时间点之差

5.通过比较x方向移动距离来判断移动方向, 以及是否应该切换到下一张图; 根据时间判断用户是否进行了左右扫动的操作

6.移动图片可以使用 translate3d来实现,开启硬件加速

7.移动一段距离需要 easeOut效果,我们可以使用 Tween算法中的easeOut来实现我们每次移动的距离; 当然也可以使用 js设置 transition动画
实现源码(仅供参考):

head头部样式



<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=.5,maximum-scale=.5">
<title>移动端轮播图</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0
}
.banner {
overflow: hidden;
width: 100%;
height: 300px
}
.banner .img-wrap {
position: relative;
height: 100%
}
.banner img {
display: block;
position: absolute;
top: 0;
width: 100%;
height: 100%
}
</style>
</head>HTML结构



<p class="banner">
<p class="img-wrap" id="imgWrap">
<img src="images/banner_3.jpg" data-index="-1">
<img src="images/banner_1.jpg" data-index="0">
<img src="images/banner_2.jpg" data-index="1">
<img src="images/banner_3.jpg" data-index="2">
<img src="images/banner_1.jpg" data-index="3">
</p>
</p>JS代码1, easeOut动画式移动,

这里的 HTMLElement.prototype.tweenTranslateXAnimate ,是给所有的HTML元素类扩展的tweenTranslateXAnimate方法

移动一段距离我们需要使用定时器来帮助我们完成,这个重复的操作



<script>
HTMLElement.prototype.tweenTranslateXAnimate = function (start, end, callback) {
var ration = 50;
var t = 0;
var vv = end - start;
var Tween = {
Quad: {
easeOut: function (t, b, c, d) {
return -c * (t /= d) * (t - 2) + b;
}
}
};

this.timer = setInterval(function () {
var dis = start + Tween.Quad.easeOut(++t, 0, vv, ration);
this.style.transform = 'translate3d(' + dis + 'px, 0, 0)';
if (vv > 0 && parseInt(this.style.transform.slice(12)) >= end) {
this.style.transform = 'translate3d(' + parseInt(dis) + 'px, 0, 0)';
clearInterval(this.timer);
callback && callback();
}
if (vv < 0 && parseInt(this.style.transform.slice(12)) <= end) {
this.style.transform = 'translate3d(' + parseInt(dis) + 'px, 0, 0)';
clearInterval(this.timer);
callback && callback();
}
}.bind(this), 4);
}
</script>touch事件部分



<script>
~function () {
var lastPX = 0; // 上一次触摸的位置x坐标, 需要计算出手指每次移动的一点点距离
var movex = 0; // 记录手指move的x方向值
var imgWrap = document.getElementById('imgWrap');
var startX = 0; // 开始触摸时手指所在x坐标
var endX = 0; // 触摸结束时手指所在的x坐标位置
var imgSize = imgWrap.children.length - 2; // 图片个数
var t1 = 0; // 记录开始触摸的时刻
var t2 = 0; // 记录结束触摸的时刻
var width = window.innerWidth; // 当前窗口宽度
var nodeList = document.querySelectorAll('#imgWrap img'); // 所有轮播图节点数组 NodeList

// 给图片设置合适的left值, 注意 querySelectorAll返回 NodeList, 具有 forEach方法
nodeList.forEach(function (node, index) {
node.style.left = (index - 1) * width + 'px';
});

/**
* 移动图片到当前的 tIndex索引所在位置
* @param {number} tIndex 要显示的图片的索引
* */
function toIndex(tIndex) {
var dis = -(tIndex * width);
var start = parseInt(imgWrap.style.transform.slice(12));
// 动画移动
imgWrap.tweenTranslateXAnimate(start, dis, function () {
setTimeout(function () {
movex = dis;
if (tIndex === imgSize) {
imgWrap.style.transform = 'translate3d(0, 0, 0)';
movex = 0;
}
if (tIndex === -1) {
imgWrap.style.transform = 'translate3d(' + width * (1 - imgSize) + 'px, 0, 0)';
movex = -width * (imgSize - 1);
}
}, 0);
});
}

/**
* 处理各种触摸事件 ,包括 touchstart, touchend, touchmove, touchcancel
* @param {Event} evt 回调函数中系统传回的 js 事件对象
* */
function touch(evt) {
var touch = evt.targetTouches[0];
var tar = evt.target;
var index = parseInt(tar.getAttribute('data-index'));
if (evt.type === 'touchmove') {
var di = parseInt(touch.pageX - lastPX);
endX = touch.pageX;
movex += di;
imgWrap.style.webkitTransform = 'translate3d(' + movex + 'px, 0, 0)';
lastPX = touch.pageX;
}
if (evt.type === 'touchend') {
var minus = endX - startX;
t2 = new Date().getTime() - t1;
if (Math.abs(minus) > 0) { // 有拖动操作
if (Math.abs(minus) < width * 0.4 && t2 > 500) { // 拖动距离不够,返回!
toIndex(index);
} else { // 超过一半,看方向
console.log(minus);
if (Math.abs(minus) < 20) {
console.log('距离很短' + minus);
toIndex(index);
return;
}
if (minus < 0) { // endX < startX,向左滑动,是下一张
toIndex(index + 1)
} else { // endX > startX ,向右滑动, 是上一张
toIndex(index - 1)
}
}
} else { //没有拖动操作

}
}
if (evt.type === 'touchstart') {
lastPX = touch.pageX;
startX = lastPX;
endX = startX;
t1 = new Date().getTime();
}
return false;
}

imgWrap.addEventListener('touchstart', touch, false);
imgWrap.addEventListener('touchmove', touch, false);
imgWrap.addEventListener('touchend', touch, false);
imgWrap.addEventListener('touchcancel', touch, false);

}();

</script>在触摸事件中最关键的参数是 pageX参数, 记录x的位置.
当然这只是一个demo,还需要进一步的优化和封装, 以便于我们用在真实的项目.

本demo仅仅是提供了一个解决问题的思路, 有了这个思路,相信各种复杂的需求也得以解决...
详解如何使用原生JS实现移动端web轮播图效果

自动切换到下一张; 手指向左或者向右移动的快时,会切换到下一张; 图片轮播是无限循环的, 我们需要采用 3 1 2 3 1的方式来实现, 即 N+2张图来实现N张图的无限循环轮播 我们通过分析现象,可以提出一个基本实现方案: 1. 手指触摸事件可以通过 touchstart touchmove touchend 3个事件来实现 2....

JavaScript:原生JS实现轮播图的几种方式

要实现JavaScript原生轮播图,有几种不同的方法可供选择。首先,一种简单直观的方式是利用绝对定位和透明度变化,通过设置图片的透明度来控制显示。这种方法代码量小,过渡自然,但缺乏左右滑动效果,适用于需求简洁的场景。另一种方法是结合绝对定位和left属性,将图片分为四个状态:激活、上一页、下一页和...

js原生轮播图?

如何用原生js和css制作轮播图1、曾经插件不太流行我就自己写,这个问题我来回答你,原生你需要对CSS跟JS都比较熟练,才能去制作,先用CSS排版出你需要的界面,之后才能去写JS。2、这个轮播图,我们通过两大模块构成;左右点击模块和姓名点击模块。然后在两者相关联来达到最终的效果。在使用js实现轮播图的...

JS制作轮播图

1、首先需要在Sublime中创建HTML文档,然后在文档的body区域中加入如下图所示的轮播图内容 2、然后我们需要在style标签中给所添加的轮播图内容声明样式,如下图所示 3、接下来我们就需要在script标签中实现轮播图的动画脚本内容了,如下图所示,注意script标签的type类型一定要是javascript 4、最后我们运行界...

简单轮播图的实现及原理讲解(js)

首先先理解该轮播图如何滚动,这里是通过控制 img_ul 的 left 值来控制显示某张图片, 为了实现“滚动”的效果,我们需要 逐渐 改变 img_ul 的 left 值,而不能直接使该值变化图片宽度的倍数。这里我们定义一个动画效果函数 Roll() 。试想下面的情况,当图片从最后一张切换到第一张时,这时就...

js原生代码实现轮播图

最简单的轮播广告 body, div, ul, li { margin: 0;padding: 0;} ul { list-style-type: none;} body { background: #000;text-align: center;font: 12px/20px Arial;} box { position: relative;width: 492px;height: 172px;background: #fff;border-radius: 5px;border: 8px...

直播app源码,使用vue-awesome-swiper创建轮播图幻灯片

首先,为了在项目中使用vue-awesome-swiper,你需要根据项目需求选择合适的引入方式。官方文档提供了两种推荐的引入策略:全局引入: 在main.js文件的入口位置,将vue-awesome-swiper库添加到项目的全局依赖中,确保它在任何需要的地方都能被访问。 按需引入: 如果你只需要在特定的组件或页面中使用轮播图...

JS特效一:图片轮播图(JS必须掌握的特效

这里介绍一种非常实用的js特效——图片轮播图。虽然这个特效在网页上很常见,但想要掌握它,还是需要一定的技术基础,特别是js方面的知识。下面我会展示一个图片轮播图的例子,它默认显示第一张图片,并且是响应式的,能够适应不同屏幕尺寸的变化。下面是需要注意的一些细节,我已经用圈圈标注出来了。此外...

bootstrap3轮播图-如何用Bootstrap制作轮播图

如下图所示 07 最后我们运行程序以后,在页面中你就可以看到如下图所示的轮播图效果了。可以看到我们上面说的轮播图焦点和左右箭头都在页面上显示出来了,如下图所示 bootstrap3的carousel图片轮播为什么无法使用 是不是引用js、css顺序错误,必须css、然后是,最后再是 可以参考 网页链接看一下 ...

js定时器轮播图?

(本文以阴阳师中“平安世界”模块的轮播图为例)这个轮播图,我们通过两大模块构成;左右点击模块和姓名点击模块。然后在两者相关联来达到最终的效果。在使用js实现轮播图的效果前,先使用HTML和CSS完善这一模块的布局。本轮播图使用8张图片。每次出现两张。我们在使用HTML和CSS布局时可以先把第一组的两...

js轮播图怎么实现 js实现左右轮播图 web轮播图怎么做 前端翻动页面停止轮播 前端轮播图代码 自动轮播图html代码 js实现轮播 js实现多个div轮播 jquery鼠标悬停轮播图
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
...把其中任意三面分上、中、下挂在旗杆上表示不同信号,一共可以组成... 质能转换爱因斯坦的形象比喻 质能转换基本概念 如何制作美味的抹茶冰激凌? 在淘宝网上开游戏卡和手机充值卡的店怎么寻找货源?O(∩_∩)O谢谢 ...它们的直径的比是( ),周长的比是( ),面积的比是( )? 很急啊!_百度... ...比是5比3,半径比是多少,直径比是多少,面积比是多少,你发现了什么... ...周长比是5比3,半径比是(),直径比是(),面积比是()。 鸡肝煮多长时间 ...是5:3,他们的直径比是(),周长比是(),面积比是(),他们的周长与自己半... 原生JavaScript中如何实现todolist功能 用双唑泰栓后第二天流出来粉色的液体怎么回? 如何开发一个完整的JavaScript组件 早上空肚吃脆枣,为什么胃疼? 枣子吃多胃疼胃出血 关于维A酸乳膏。 求一个最多 四字 的形容东西乱但又优美的词 请问“”创业”用英语怎么写??不懂的不要回答谢谢。 第一次跟女友约会送什么礼物好呢? 中国商品期货有哪些品种 离京开市场最近的地铁在哪 为什么手在缓缓运动过程中,感觉到手有血液流动的感觉 有时候睡觉能感觉到全身血液的流动,心跳跳的不快很舒服,懒得动,感觉... 啊贺朝你tm怎么这么大 ...油从炼厂到终端客户(加油站)全过程,作为掮客怎样能挣到钱?_百度知... 手游用什么手柄好? 为什么iphone6s耗电量快 雨天光脚踩泥会感染寄生虫吗? 2OO5年1月23日出生的现在多大了? 高考成绩447分 报考什么学校的专业好?拜托了各位 谢谢 旅行青蛙手信胖胖邀约怎么准备 广州江南批发市场还有东旺市场有什么区别? 经费不足与教师编制不均衡成义务教育学校难题 理肤泉清痘净肤特润舒护乳好用吗?理肤泉清痘净肤特润舒护乳价格_百度知... 祛痘印洗面奶 华泰微医保多次赔付重疾险线上怎么买?靠谱吗? 葛屿村到中亭街坐几路公交 正荣润城有公交车直达到中亭街吗 视频和音频有很多种接线端子,比如rca,bnc等,他们有什么区别?怎么... 从塔头到中婷街有几路公交车 利嘉鞋城至中亭街坐几路公交车 从群众路到中亭街口怎么坐公交车,最快需要多久 李晟李若嘉谁漂亮 小麦控旺药什么时候打合适(小麦控旺最佳时期是三月几号) 13年的奥迪A6L左面大灯全不亮(转向。大灯。雾灯。日间行车灯)请求解 我刚买的2012款奥迪A6L 30 开的第3天右边的日行灯就不亮了,去了4S店N... 马来酸多潘立酮片的儿童用药 霸气的枪怎么画 白果园水鬼脑打不到 煮鸡蛋需要多长时间最好吃