最近去面试了,对方要求我在一个星期内用原生的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全屏轮播插件的更多相关文章

  1. Vue与swiper想结合封装全屏轮播插件

    项目需求介绍: 1.页面图文混排, 2.点击图片后全屏展示图片,并在底部显示文字,如果没有则不显示 3.关闭全屏后依然停留在上次浏览的位置 4.浏览图片时,不管点击的哪张图片,全屏展示的时候也要显示这 ...

  2. 全屏轮播插件 fullPage.js应用(基础版兼容IE7, 背景图版兼容IE8)

    /** * fullPage 1.4.5 * https://github.com/alvarotrigo/fullPage.js * MIT licensed * * Copyright (C) 2 ...

  3. 图片全屏轮播插件poposlides

    jQuery轻量级全屏自适应焦点图插件poposlides 在线演示本地下载

  4. 基于Ascensor.js全屏切换页面插件

    今天给大家分享一款基于Ascensor.js全屏切换页面插件,这款实例 适用浏览器:IE8.360.FireFox.Chrome.Safari.Opera.傲游.搜狗.世界之窗.效果图如下: 在线预览 ...

  5. 全屏banner及全屏轮播

    一.全屏banner 1.设置网页图片全屏banner <!DOCTYPE html> <html lang="en"> <head> < ...

  6. 纯js写图片轮播插件

    最近终于写成了自己创作的图片轮播插件,使用原生js编写.与目前网上流行的轮播插件相比,功能和效果稍弱,但是使用起来相当方便. 先看html代码 <!DOCTYPE html> <ht ...

  7. javascript无缝全屏轮播

    虽然平时能利用插件来实现,但是总是觉得,如果连个无缝轮播都写不出来,还玩个毛线: 其实现在还真的是玩毛线,因为代码都是别人的,不过嘛,很快就变成是我的啦! 代码还没封装成插件,其实我也还没弄清楚. 下 ...

  8. 实现全屏轮播,并且轮播div中的文字盒子一直自动垂直居中

    效果如下: 直接上代码了: 说明:轮播图基于swiper.js,自行下载.css在最后 <!DOCTYPE html> <html lang="en"> & ...

  9. Fullpage.js全屏滚动jQuery插件

    兼容性: 支持 IE8+ 及其他现代浏览器. 主要功能: 1.支持鼠标滚动: 2.支持前进后退键盘控制; 3.多个回调函数; 4.支持手机.移动设备; 5.支持窗口缩放自动调整; 6.可设置滚动宽度. ...

随机推荐

  1. bash检查文件格式

    情形描述:最近在做一个ETL的项目,用的是CLoverETL,需要在拿到文件后对文件格式进行检验,以决定是否继续. 主要功能是检查每个文件中有几个“|”符号,项目中约定以该符号来作为分隔,所以检查每个 ...

  2. 解析利用wsdl.exe生成webservice代理类的详解

    利用wsdl.exe生成webservice代理类:根据提供的wsdl生成webservice代理类1.开始->程序->Visual Studio 2005 命令提示2.输入如下红色标记部 ...

  3. Scala伴生类和伴生对象

    单例对象与类同名时,这个单例对象被称为这个类的伴生对象,而这个类被称为这个单例对象的伴生类.伴生类和伴生对象要在同一个源文件中定义,伴生对象和伴生类可以互相访问其私有成员.不与伴生类同名的单例对象称为 ...

  4. easyui datagrid 跨页选择

    $.fn.extend( memberList ,{ quickSearch : function() { var time1 = new Date(); /* this.datagrid.datag ...

  5. 借助取色工具ColorPix对Pycharm编辑器设定自己喜欢的代码颜色_20161202

    1.Pycharm编辑器怎么设定自己喜欢的颜色,前几天看爬虫博客,看博主贴出的代码颜色很是喜欢,如下图,设置了好多次找不到他设定的颜色. 2.下班回家想起来之前做表的时候用到过一个取色工具ColorP ...

  6. (转)UVM内容梗概

    1. 类: 面向对象基础传统的面向对象编程与systemverilog类的特点,类的定义,成员与方法,构造函数,对象的复制和深/浅拷贝,父类/子类关系,类的继承,作用域的规则,对象的句柄以及赋值,方法 ...

  7. 解决方法:An error occurred on the server when processing the URL. Please contact the system administrator

    在WINDOWS7或SERVER2008上安装了IIS7.5,调试ASP程序时出现以下错误: An error occurred on the server when processing the U ...

  8. 转 系统级编程语言性能PK

    http://www.solidot.org/story?sid=35754 看了此文,为什么我现在如此看好Rust C/C++已经统治系统编程很久,除了ObjectiveC之外语言都无法获得很高的关 ...

  9. lnmp重置mysql密码

    第一种方法:用军哥的一键修改LNMP环境下MYSQL数据库密码脚本一键脚本肯定是非常方便.具体执行以下命令: wget http://soft.vpser.net/lnmp/ext/reset_mys ...

  10. [转载] Android Studio 上第一个 Xposed 模块

    本文转载自: http://www.open-open.com/lib/view/open1451364108964.html 环境: 已root手机一枚 Android Studio一枚 官方文档参 ...