最近去面试了,对方要求我在一个星期内用原生的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. Linux下的压缩和解压缩命令——compress/uncompress

    compress命令 compress命令使用"Lempress-Ziv"编码压缩数据文件.compress是个历史悠久的压缩程序,文件经它压缩后,其名称后面会多出".Z ...

  2. Swift -运算符和循环结构

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Menlo; color: #4dbf56 } p.p2 { margin: 0.0px 0. ...

  3. 基于SWFUpload的angular上传组件

    回顾 由于工作内容比较多,特别是架构方面,需要耗费很多的时间调整.重构,因此很久没有写文章了. 话就不多说了,直接进入主题. 实现 首先分析一下SWFUpload初始化的时候,需要传入当前触发上传的元 ...

  4. sublime php语法检查

    安装sublimelinter 安装sublimelinter-php 设置sublimelinter 进入SublimeLinter文件夹改动 SublimeLinter.sublime-setti ...

  5. 前端学习:html基础学习二

    3.文档设置标记上-格式标记(主要内容标记<br><p><center><pre><li><ul><ol><d ...

  6. Unreachable statement

    public boolean onQueryTextSubmit(String s) { if (sv != null) { // 得到输入管理对象 InputMethodManager imm = ...

  7. 架构.Net 到 Linux

    nginx + .net core + mysql + radis + rabbitmq

  8. ASP.Net Core 2.2 MVC入门到基本使用系列 (三)(转)

    本教程会对基本的.Net Core 进行一个大概的且不会太深入的讲解, 在您看完本系列之后, 能基本甚至熟练的使用.Net Core进行Web开发, 感受到.Net Core的魅力. 本教程知识点大体 ...

  9. solr 使用指定数据源

    1,将solr 解压,我们观察发现它其实即可以是web服务也可以做数据分析 数据库 2,我们在example目录下新建一个hai的文件夹,用于存放数据 参考solr 目录,将solr.xml 复制一份 ...

  10. 树型结构递归 实体递归 JSON格式

    用递归实现无限级菜单,产品分类,盖楼式评论.留言等功能. 下列代码不能直接使用 CREATE TABLE [dbo].[P_Category]( [Code] [varchar](36) NOT NU ...