关于最近在做的一个js全屏轮播插件
最近去面试了,对方要求我在一个星期内用原生的js代码写一个全屏轮播的插件,第一想法就是跟照片轮播很相似,只是照片轮播是有定义一个宽高度大小已经确定了的容器用来存储所有照片,然后将照片全部左浮动,利用margin-left的值不断变化,来改变显示哪张照片,当达到最后一张的时候,将第一张照片appendChild到最后一张照片的后面,如果有左右移动的话,当到达第一张照片时,还要继续左移动的话,就将最后一张照片利用insertBefore,将最后一张照片放在第一张照片的前面,这两个方法都只是改变子元素的顺序而已,并没有增加子元素。
上面说的是照片滚动要怎么做,接下来开始说一下我制作js全屏滚动插件的过程。
因为之前的时候,对于scrollWidth和clientWidth和offsetWidth的区分还是不是很明确,所以认真测试了一下,这个网址也讲得很清楚:http://www.cnblogs.com/kongxianghai/p/4192032.html 后来选择使用了document.documentElement.clientWidth,刚开始使用document.body.clientWidth,的出来的结果一直有偏差,是因为Html文件的开头使用了dtd定义文件的W3C标准,所以才要使用document.documentElement.clientWidth,通过document.documentElement.clientWidth和document.documentElement.clientHeight来获取页面的宽高度之后,就可以动态的给页面设定宽高度了,这个过程中,需要先定义一个容器,叫做div1吧,div1的宽度设定为100%,高度先给一个确定的值,之后再通过js改变这个div的宽高度,使其宽高度为一个页面的宽高度,同时有一个要注意的是,div1要设定它的overflow为hidden,这样的话,就不会因为里面的元素而撑开div1的大小了。之后再在div1里面定义一个子容器,叫做div2吧,div2的宽度要容纳所有的子页面,这个宽度可以通过获取子页面的个数,将利用document.documentElement.clientWidth得到的页面宽度乘于页面数,之后得到的长度就是div2的宽度了,高度跟页面高度一样,这个容器是关键,以后用它来移动从而不断显示页面。之后再定义每个页面,页面的宽高度也是先设定一个值,之后再通过js动态赋值。现在html和css的代码就大概成功了。要注意,我们是制作插件,所以这个过程中,不能使用id来获取元素,只能通过class来获取元素。
实现后的代码就是这样:
这里要注意一个问题,body也要设置为overflow:hidden,要不然的话,到时出现页面大小变化的时候,右边和下方会出现一个滚动条大小的空白,这就是因为body没有设定overflow:hidden而导致的。
html和css代码搞定了,之后就开始着手处理js代码实现功能了~~
实现功能之前,首先要先了解一下闭包和原型的含义:所谓闭包,就是每个函数或者变量都有一个作用域,比如你将index定义在aa里面,那index的作用域就是在aa这个函数里面,这就是闭包的简单理解。
function aa(){
var index = 1;
}
PS:在必须不可的情况下,才定义全局变量,要不然的话,还是将变量都定义在一个局部作用域中,即定义在函数里面,这样的话,就减少全局变量的污染以及一些风险(比如外部随便更改你全局变量的值,导致一些不可预料的后果)。
原型,就是要涉及到prototype这个属性了,每个对象,都有一个prototype属性,指向它的原型对象,这样,原型对象有的属性已经方法都能被所有的对象实例共享。
同时,还要注意一下,window.onload = function(){}如果在同一个html页面中同时引用两个文件,这两个文件都包含了window.onload = function(){},那么后一个window.onload = function(){}会覆盖前一个window.onload = function(){},所以我们在做插件给别人用的时候,可以用下列代码:
if (addEventListener) {
window.addEventListener('load', 函数名);
} else {
window.attachEvent('onload', 函数名);
}
这样的话,就相当于window.onload = function(){函数名;}了。
接下来开始代码的实现~~
其实js代码的实现主要分两部分,一、初始化页面各种参数,通过document.documentElement.clientWidth来获取页面宽度,document.documentElement.clientHeight来获取页面的高度,然后设置各种参数的值,使页面全屏显示。二、点击左右箭头的移动实现,设置临界值。
接下来分步讲一下具体的实现,首先要设定一个变量,用来记录到达第几个页面,比如设置第一个页面为0,之后根据每个页面前面有几个页面,将页面数乘于页面宽度,就得到div2.style.left应该设置的距离了,注意offsetleft是无法赋值的,只能获取。比如当第一个页面即 0 的时候,其div2.style.left就为0 * document.documentElement.clientWidth,这样就可以不断控制页面的div2.style.left,从而来移动div2这个容器,来使显示的页面不断变化。
然后就是页面左移动的时候,当到达最后一个页面的时候,要确定边界。同时lock是为了防止多次点击,当点击一次之后,页面还没完全切换好,lock设置为0,这样就无法再连续点击,确保不会产生多条线程,影响setTimeout的速度。绿色字体的代码原本是放在setTimeout外面的,可是因为setTimeout会有延迟,所以导致index = index + dir;这句话先于setTime(speed, time, dir, innerIndex);执行,从而导致页面的参数都先增加或者减少1,所以我就把index = index + dir;放进setTimeout里面,这样就能确保是setTime()先执行,才执行index = index + dir;这一条语句了。(将index = index + dir;放在外面的代码看后面的截图,截图中的代码都重新设定了的,也能正常运行。)
Slide.prototype.move = function(speed, time, dir) {
var innerIndex = index;
if (lock == 0) {
lock = 1;
setTimeout(function() {
setTime(speed, time, dir, innerIndex);
index = index + dir;
}, time);
}
}
function setTime(speed, time, dir, innerIndex) { //speed:移动速度;time:每次移动时间;dir:决定左右移动,左为-1,右为1
if (innerIndex == (slidePage.length - 1) && dir == 1) {//左移动且到达最后一个页面的时候
slideContainer.appendChild(slidePage[0]);
innerIndex = innerIndex - dir;
index = innerIndex;
slideContainer.style.left = -innerIndex * cWidth + "px";
}
if (innerIndex == 0 && dir == -1) {//右移动且到达第一页页面的时候
slideContainer.insertBefore(slidePage[slidePage.length - 1], slidePage[0]);
innerIndex = innerIndex - dir;
index = innerIndex;
slideContainer.style.left = -innerIndex * cWidth + "px";
} else if (Math.abs(Math.abs(slideContainer.offsetLeft) - (innerIndex + dir) * cWidth) > 0 && Math.abs((innerIndex + dir) * cWidth - Math.abs(slideContainer.offsetLeft)) >= Math.abs(speed)) {
slideContainer.style.left = slideContainer.offsetLeft + speed + "px";
} else {
slideContainer.style.left = slideContainer.offsetLeft + (Math.abs(slideContainer.offsetLeft) - (innerIndex + dir) * cWidth) + "px";
lock = 0;
return;//注销这一条线程
}
setTimeout(function() {
setTime(speed, time, dir, innerIndex);
}, time)
}
上图为未优化之前的代码,将index = index + dir;放在setTimeout外面之前的代码。
之后我发现其他插件在页面改变大小的时候,页面的大小也会改变,移动还是能正常进行,所以我就用了下面这个事件
window.onresize = function(){
Slide.prototype.initialize(80,20);
}
重新调用了一个初始化函数,可是发现缩小页面的时候,滚动就出问题了,滚动几圈之后,页面变大,就变成了下列这样:不是一个完整的单独的页面。
后来发现,是因为我每次改变页面大小之后,虽然重新初始化了页面的宽高度,可是初始化函数里面少了一句话来初始化页面的left距离。
于是于,我加上了slideContainer.style.left = -index * cWidth + "px";
可是问题来了,现在页面是正确了,怎么缩小都可以了,可是出现了这个:右边和下方出现了滚动条大小的空白,于是乎,才发现body没有设置overflow:hidden,这样才能保证页面内容超过body大小的时候,不会出现滚动条。
至此,滚动插件已经做好了,用户调用的时候只需要引入css文件和js文件,套用html代码模板,js代码写上new slide = Slide(); initial(xx,xx);
这两句话,就可以直接调用了。
关于最近在做的一个js全屏轮播插件的更多相关文章
- Vue与swiper想结合封装全屏轮播插件
项目需求介绍: 1.页面图文混排, 2.点击图片后全屏展示图片,并在底部显示文字,如果没有则不显示 3.关闭全屏后依然停留在上次浏览的位置 4.浏览图片时,不管点击的哪张图片,全屏展示的时候也要显示这 ...
- 全屏轮播插件 fullPage.js应用(基础版兼容IE7, 背景图版兼容IE8)
/** * fullPage 1.4.5 * https://github.com/alvarotrigo/fullPage.js * MIT licensed * * Copyright (C) 2 ...
- 图片全屏轮播插件poposlides
jQuery轻量级全屏自适应焦点图插件poposlides 在线演示本地下载
- 基于Ascensor.js全屏切换页面插件
今天给大家分享一款基于Ascensor.js全屏切换页面插件,这款实例 适用浏览器:IE8.360.FireFox.Chrome.Safari.Opera.傲游.搜狗.世界之窗.效果图如下: 在线预览 ...
- 全屏banner及全屏轮播
一.全屏banner 1.设置网页图片全屏banner <!DOCTYPE html> <html lang="en"> <head> < ...
- 纯js写图片轮播插件
最近终于写成了自己创作的图片轮播插件,使用原生js编写.与目前网上流行的轮播插件相比,功能和效果稍弱,但是使用起来相当方便. 先看html代码 <!DOCTYPE html> <ht ...
- javascript无缝全屏轮播
虽然平时能利用插件来实现,但是总是觉得,如果连个无缝轮播都写不出来,还玩个毛线: 其实现在还真的是玩毛线,因为代码都是别人的,不过嘛,很快就变成是我的啦! 代码还没封装成插件,其实我也还没弄清楚. 下 ...
- 实现全屏轮播,并且轮播div中的文字盒子一直自动垂直居中
效果如下: 直接上代码了: 说明:轮播图基于swiper.js,自行下载.css在最后 <!DOCTYPE html> <html lang="en"> & ...
- Fullpage.js全屏滚动jQuery插件
兼容性: 支持 IE8+ 及其他现代浏览器. 主要功能: 1.支持鼠标滚动: 2.支持前进后退键盘控制; 3.多个回调函数; 4.支持手机.移动设备; 5.支持窗口缩放自动调整; 6.可设置滚动宽度. ...
随机推荐
- 通过SQL语句提取存储过程中的内容
首先,列出服务器上所有数据库. -- 获取数据库列表 SELECT name FROM master.dbo.sysdatabases ORDER BY name 其次,这是一种让所有的用户从数据库中 ...
- 【解决】SharePoint外部列表保存的日期/时间值不正确
[问题描述]: 在SharePoint中创建一个外部列表后,通过工作流或直接通过外部列表中的新增向外部列表添加数据项.通过外部列表或数据库查看添加的数据项时发现日期类型字段的值都不正确,像是差了若干个 ...
- c/c++ 对象内存布局
一.对象内存查看工具 VS 编译器 CL 的一个编译选项可以查看 C++ 类的内存布局,非常有用.使用如下,从开始程序菜单找到 Visual Stdio 2012. 选择 VS 的命令行工具,按如下格 ...
- C++ 删除字符串的两种实现方式
C++实现删除给定字符串的给定字符串思路主要有这么几种实现方式: 1.KMP算法2.用STL的string的 find,然后用erase3.用C的strstr找到字串位置,然后用strncpy写到新串 ...
- javascript高级程序设计--笔记01
概述 JavaScript的实现包含三个部分: 1 核心(ECMAScript) 提供核心语言功能 2 文档对象模型(DOM) 一套提供了访问以及操作网页内容的API 3 浏览器对象模型( ...
- spark Mllib基本功系列编程入门之 SVM实现分类
话不多说.直接上代码咯.欢迎交流. /** * Created by whuscalaman on 1/7/16. */import org.apache.spark.{SparkConf, Spar ...
- Cocos2d-JS 自定义loading界面
[转]http://blog.csdn.net/et_sandy/article/details/41415047 环境: win7 64位 Cocos2d-JS v3.1 Cocos Code ID ...
- (转)SpyGlass工具介绍
Spyglass工具有五大模块: lint, CDC(多时钟域检查), LP(低功耗),Constraint(约束),DFT(可测试性). 一,在RTL层面上预估芯片性能,从而引导设计人员开发出更加 ...
- nginx 命令
nginx 命令 sudo /etc/init.d/nginx configtest 测试是否配置有错 sudo /usr/local/nginx/sbin/nginx -s reload ...
- LoadRunner ---手动关联与预关联
手动关联 如果脚本很长,那么我们想找到一个脚本中哪些地方是需要关联的并不是一件容易的事情.这时,我们可以通过脚本对比的方法找 ...