基于setTimeout制作滚动广告板
很多网站在其门户页面的上方正中央都会放置一个滚动广告板,用于显示一些推荐信息,用户点击即可进入浏览。比较常见的就是各个公司的官网,电商网站的首页等。
下面是天猫的滚动广告板截图。
其实,不需要借助于什么复杂的技术,仅仅通过setTimeout函数,就能实现这种滚动广告板的效果。
分析
仔细观察这个滚动广告版,我们发现,其功能无非就两点:
- 无限循环的不停滚动显示每一条广告
- 当点击某一个广告的索引时,以那条广告为起点,无限循环滚动
先分析一下第一个功能点。
要做到无限循环的不停滚动显示每一条广告,那么只需要关注两个相邻广告页的切换(暂且称为函数doSwitch),然后通过设置定时任务不停的运行doSwitch就可以了。因此,我们有了一个基本的雏形:
function doSwitch() {
//switch adjacent ad pages
}
function autoSwitch() {
doSwitch();
};
setTimeout(autoSwitch, someInterval)
现在,我们只需要重点关注switch的实现就可以了。
上面截图中,广告页通过淡入淡出效果来进行切换,很容易就联想到css3中的opacity属性(天猫也是这么实现的),但是考虑到IE8的存在,opacity就不适用了,由于具体的切换效果与今天的主题关系不大,所以改成了横向滚动切换效果。
横向滚动有很多种实现效果,最直接的方式,就是通过margin-left来实现。设广告页的宽度为w,以当前广告页左边的边框为基准线,将当前广告页的margin-left由0逐渐递减至-w,将下一广告页的margin-left由w逐渐减至0(广告板的父容器设置overflow:hidden)。因此,doSwitch可以简单实现如下:
function doSwitch() {
var curPage = document.getElementById(curPageId),
nextPage = document.getElementById(nextPageId);
curPage.style.marginLeft -= step; // 此处忽略了单位处理
nextPage.style.marginLeft -= step;
if (nextPage.style.marginLeft > 0) {
setTimeout(doSwitch, someInnerInterval);
} else {
setTimeout(autoSwitch, someInterval);
}
}
由于切换效果的时间应该远小于广告停留的时间,所以此处someInnerInterval小于someInterval.
注意到,每次广告页的切换,广告页下方的索引按钮也会跟着切换,因此,上方的autoSwitch函数中还要增加一项设置当前选中索引的功能,暂且成为setCurIndex函数,则autoSwitch实现修改如下:
function autoSwitch() {
setCurIndex();
doSwitch();
}
到此,无限循环滚动显示广告的功能就完成了.
上面的代码只做基本原理介绍,实际操作过程中还有很多细节需要处理。
再看第二个功能点。
当用户点击某个广告页的索引时,当前广告会立即被切换到选中的广告页,并从选中的广告页开始循环滚动。咋一看跟功能点一很像,似乎只需要在用户点击某个索引的时候将当前广告页设置为用户选中的广告页就可以了。但是很多时候,最直接的想法往往是不对的,这里需要考虑到setTimeout的原理。
setTimeout函数的正确使用姿势应该像下面的代码一样:
var timeout = setTimeout(function () {
//do something after at least 1s
}, 1000);
// clearTimeout(timeout); //cancel setTimeout handler function
我们知道,JavaScript是单线程的,定时器只是计划代码在未来的某个时间点执行,但是,执行时机是不能保证的。在页面的生命周期中,不同时间可能有其他代码控制着JavaScript线程。例如在页面下载完后的代码运行、事件处理程序、Ajax请求的回调函数等都必须使用同样的线程来执行。实际上,浏览器负责进行排序,指派某段代码在某个时间点运行的优先级。在浏览器内部管理着一个代码队列,随着页面生命周期的推移,代码会按照执行顺序添加入队列。例如,当某个按钮被按下时,它的事件处理程序代码就会被添加到队列中,并在下一个可能的时间里执行。当接到某个Ajax响应时,回调函数的代码会被添加到队列。浏览器通过事件循环的机制从这个队列中取出处理函数代码并执行。
定时器对队列的工作方式是,在指定时间过去后,将代码插入队列。请注意,给队列添加代码并不意味着它会立即执行,而只能表示它会尽快执行。与setTimeout函数成对出现的是clearTimeout函数,用于取消setTimeout设置的延时执行的函数。该函数只接受一个参数,那就是setTimeout返回的延时调用ID。
回到刚才的问题中,功能一中,通过setTimeout函数,不停的将doSwitch和autoSwitch函数添加到队列中,如果当用户点击某个广告页索引时,只是简单的将当前广告设置为选中的广告页,然后调用autoSwitch的话,将会导致两个无限循环滚动同时运行,这必将导致广告页显示的混乱。
那么如何解决这个问题呢?
当用户点击某个索引时,我们只需要终止之前一直运行的循环滚动,然后开启新的循环滚动即可。那么问题就聚焦在如何终止上一个循环滚动上面来了。实际上,我们可以通过clearTimeout来实现。我们只需要在doSwitch中添加一个状态检测,如果用户当前点击了某个索引,则退出函数执行。样例如下:
function doSwitch() {
if (paused) {
return;
}
// other
}
这时候,我们只需要在用户点击某个广告索引时,设置paused为true,然后在新一轮的循环滚动开始前将paused设置为false就可以了。代码如下:
indexDom.onclick = function () {
setCurIndex();
paused = true;
setTimeout(function () {
paused = false;
autoSwitch();
}, someInterval);
}
需要注意的一点是,这里的someInterval与功能点一中的someInterval要保持相同。由于someInnerInterval小于someInterval,所以在下一个循环滚动开始之前,上一个循环滚动已经停止了。
到此,实际上基本功能就已经结束了,但是在完成基本功能之后,我们还要照顾到异常场景的存在。这里就需要处理短时间内连续点击不同索引的情况。
其实也很简单,只需要在onclick时间处理函数中保存一个curClick索引,然后在延时函数中比对curClick是否与当前的curIndex一致就可以了。
所以上面的onclick可以改写如下:
indexDom.onclick = function () {
var curClick = indexDom["data-index"]; //get the index of indexDom
setCurIndex();
curIndex = curClick;
setTimeout(function () {
if (curIndex !== curClick) {
return;
}
paused = true;
setTimeout(function () {
paused = false;
authSwitch();
}, someInterval)
}, 0);
}
到此,整个滚动广告板就做完了,但是实现功能仅仅是第一步,下一步还需要将其组件化,将一些内部状态隐藏,抽象出组件接口。在使用的时候,只需要实例化一个组件实例,然后使用必要的数据调用组件接口就可以了。
下面是实现的效果图:
源代码稍后放出:)
基于setTimeout制作滚动广告板的更多相关文章
- 基于html5页面滚动背景图片动画效果
基于html5页面滚动背景图片动画效果是一款带索引按钮的页面滚动动画特效代码.效果图如下: 在线预览 源码下载 实现的代码. html代码: <div id="fullpage&q ...
- 基于JQuery实现滚动到页面底端时自动加载更多信息
基于JQuery实现滚动到页面底端时自动加载更多信息 关键代码: 代码如下: var stop=true; $(window).scroll(function(){ totalheight = par ...
- 【转】基于laravel制作APP接口(API)
这篇文章主要介绍了基于laravel制作APP接口(API)的相关资料,需要的朋友可以参考下 前期准备 前言,为什么做以及要做个啥本人姓小名白,不折不扣编程届小白一名,但是自从大一那会儿接触到编程这件 ...
- 基于CSS3制作的鼠标悬停动画菜单
之前分享了好多款css3实现的鼠标悬停效果.今天再给大家带来一款基于CSS3制作的鼠标悬停动画菜单.这款菜单适用浏览器:360.FireFox.Chrome.Safari.Opera.傲游.搜狗.世界 ...
- 制作滚动视图(ScrollView)
怎样判断是否应当使用滚动视图 所谓的滚动视图,是指一个可以滑动的视窗,视窗大小和位置固定不变,视窗内的内容用户可以通过手指滑动或者拖动滚动天来进行滚动浏览. 滚动视图的目的是为了解决同类内容过多,一个 ...
- Docker系列06—基于容器制作镜像并上传到Docker Registry
本文收录在容器技术学习系列文章总目录 1.制作镜像 1.1 镜像的生成途径 基于容器制作 dockerfile,docker build 本篇主要详细讲解基于容器制作镜像:基于dockerfile 制 ...
- 基于jQuery实现滚动新闻代码下载
分享一款基于jQuery实现滚动新闻代码下载.这是一款基于bootstrup 3实现的响应式jQuery滚动新闻插件.效果图如下: 在线预览 源码下载 实现的代码. html代码: <div ...
- 利用jquery制作滚动到指定位置触发动画
<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>利用 ...
- Expression Design与Blend制作滚动的小球动画教程
原文:Expression Design与Blend制作滚动的小球动画教程 一,开发工具 Microsoft Expression Design & Blend 4.0 (3.0亦可). 这两 ...
随机推荐
- 汉字转拼音类EcanConvertToCh
/// <summary> /// 汉字转拼音类 /// </summary> public class EcanConvertToCh { //定义拼音区编码数组 priva ...
- 小议C#接口的隐式与显示实现(续)
上文连接,讲的比较模糊,而且调用起来感觉比较混乱 http://www.cnblogs.com/walleyekneel/p/3581489.html 这次改为显式接口调用,可能项目也有这个一个需求 ...
- 手机打车APP的机遇与挑战
所谓打车APP,就是个能安装在手机上的打车软件.原理是通过GPS进行定位,能够搜索附近的空车信息然后反馈给用户.同样的,空车信息也会反馈给用户.一般这种啊APP都是跟地图类软件一起的.比如百度地图,谷 ...
- C#中如何向数组中动态添加元素
转自:https://blog.csdn.net/qq_35938548/article/details/78325558 背景:现需要向数组中循环插入字符串,但C#中的数组是不支持动态添加元素的,只 ...
- Partial关键字
Partial关键词定义的类可以在多个地方被定义,最后编译的时候会被当作一个类来处理. 首先看一段在C#中经常出现的代码,界面和后台分离,但是类名相同. public partial class Fo ...
- angular学习文章
https://www.jianshu.com/p/86c6249a2069 angular.cn https://segmentfault.com/a/1190000008754631
- Mybatis-generator逆向工程
$.Mybatis-generator介绍 MyBatis Generator(MBG)是MyBatis MyBatis 和iBATIS的代码生成器.它将为所有版本的MyBatis以及版本2.2.0之 ...
- python-输入
1. python2版本中 咱们在银行ATM机器前取钱时,肯定需要输入密码,对不? 那么怎样才能让程序知道咱们刚刚输入的是什么呢?? 大家应该知道了,如果要完成ATM机取钱这件事情,需要先从键盘中输入 ...
- Flutter的使用教学笔记
QQ交流群 Flutter 程序开发群:766307130 教程 官方实战 使用Flutter 构建精美的页面 云在千峰 博主一直是从事 Android 开发的,所以主要从 Android 技术角度来 ...
- JMeter Bean Shell
1.什么是bean Shell BeanShell是一种脚本语言,一种完全符合java语法的java脚本语言,并且又拥有自己的一些语法和方法,beanShell是一种松散类型的脚本语言(这点和JS类似 ...