zoukankan      html  css  js  c++  java
  • 跟着《beginning jquery》学写slider插件并借助自定义事件改进它

    《beginning jquery》是一本很不错的学习jquery的书,作者的讲解深入浅出,很适合初学者,在最后一章里面,作者把前面所有的点结合起来完成了一个轮播图的jquery插件。实现了自动播放,键盘和鼠标控制。但是,借助jquery的自定义事件来优化这个插件,可以使逻辑更清楚。

    效果图

    首先贴一下作者(Jack Franklin)的原程序:

    (function($) {
    $.fn.slider = function(options) {
    var defaults = {duration: 1000};
    var settings = $.extend({}, defaults, options);
    return this.each(function() { // store some initial variables
    var $slider = $(this);
    var $sliderList = $slider.children("ul");
    var $sliderItems = $sliderList.children("li");
    var $allButtons = $slider.find(".button");
    var imageWidth = $sliderItems.first().children("img").width();
    var $buttons = {
    forward: $allButtons.filter(".forward"),
    back: $allButtons.filter(".back")
    };
    var endMargin = -(($sliderItems.length - 1) * $sliderItems.first().children("img").width());
    var animateSlider = function(direction, callback) {
    $sliderList.stop(true, true).animate({
    "margin-left" : direction + "=" + imageWidth },
    settings.duration,
    callback);
    var increment = (direction === "+" ? -1 : 1);
    updateIndex(currentIndex + increment);
    };
    var animateSliderToMargin = function(margin, callback) {
    $sliderList.stop(true, true).animate({"margin-left": margin}, settings.duration, callback);
    };
    var getLeftMargin = function() {
    return parseInt($sliderList.css("margin-left"), 10);
    };
    var isAtBeginning = function() {
    return getLeftMargin() === 0;
    };
    var isAtEnd = function() {
    return getLeftMargin() === endMargin;
    };

    var updateIndex = function(newIndex) {
    currentIndex = newIndex;
    $index.text(currentIndex);
    };
    var triggerSlider = function(direction, callback) {
    var isBackButton = (direction === "+");
    if(!isBackButton && isAtEnd()) {
    animateSliderToMargin(0, callback);
    updateIndex(1);
    }
    else if(isBackButton && isAtBeginning()) {
    animateSliderToMargin(endMargin, callback);
    updateIndex(totalImages); }
    else {
    animateSlider(direction, callback);
    }
    };
    $allButtons.on("click", function(event) {
    var isBackButton = $(this).hasClass("back");
    triggerSlider((isBackButton? "+" : "-"));
    event.preventDefault();
    });
    $(document.documentElement).on("keyup", function(event) {
    if(event.keyCode === 37) {
    triggerSlider("+");
    }
    else if (event.keyCode === 39) {
    triggerSlider("-");
    }
    });
    });
    };
    })(jQuery);

    这里没有添加键盘事件和自动播放功能,实现了鼠标点击back和forward按钮使图片滚动。当到达最后一张时,点击forward会回到第一张;当第一张图片显示并点击back按钮时,则会显示最后一张,从而实现循环滚动。通过读代码可以看出,作者定义了比较多的函数来实现这个过程。定义的相关函数有:

    判断图片位置函数:

    isAtBeginning(),
    isAtEnd()

    DOM函数和动画函数:

    animateSliderToMargin(),
    updateIndex()

    事件处理函数

    triggerSlider()

    作者的思路是click首先触发图片移动事件,然后再更新索引,但是换一种方式考虑:

    1.前进后退两个按钮只控制index的变化。就是只控制一个number的增加和减小。

    2.将索引变化看作一个事件,当索引发生变化时相应的margin-left便可以计算出来。

    3再通过自定义事件,当索引发生变化时,触发(indexChange)事件,改变slider元素的margin-left值。实现图片的切换。

    这样所有逻辑都会在操作index这个数上面,而图片切换只是响应index的变化。这样逻辑上会更清晰,也容易写出更简单紧凑的代码。如下:

    (function($) {
    $.fn.slider = function(options) {
    var defaults = {duration:1000,direction:'left',animationDelay: 5000};
    var settings = $.extend({}, defaults, options);
    return this.each(function() {
    var $slider = $(this),
    $sliderList = $slider.children("ul"),
    $sliderItems = $sliderList.children("li"),
    $itemLen=$sliderItems.length,
    $allButtons = $slider.find(".button"),
    $forward= $allButtons.filter(".forward"),
    $back=$allButtons.filter(".back"),
    $counter=$('#counter'),
    counter= 1,
    type='margin-'+settings.direction,
    timer=null,
    imageWidth=$sliderItems.find('img').width();
    //-----------------------------jquery Map-----------------------------

    //-----------------------------utility method-----------------------------
    function counterToMargin(count){
    return (1-count)*imageWidth;
    }
    function sliderWay(){
    var obj={};
    obj[type]=counterToMargin(counter);
    return obj;
    }
    function counterChange(flag){
    if(flag==='+'){
    counter<$itemLen?(counter++):counter=1;
    }
    else if(flag==='-'){
    counter>1?(counter--):counter=$itemLen;
    }
    }

    var automaticSlide = function() {
    timer=setTimeout(function () {
    counterChange('+');
    $sliderList.trigger('counterChange');
    automaticSlide();
    },settings.animationDelay);
    };
    timer =setTimeout(automaticSlide,settings.animationDelay);
    var resetTimer = function() {
    if(timer) {
    clearTimeout(timer);
    }
    timer = setTimeout(automaticSlide, 30000);
    };
    //-----------------------------event methods----------------------------
    $sliderList.on('counterChange',function(){
    resetTimer();
    var $this=$(this);
    $this.stop(true,true).animate(sliderWay(),settings.duration);
    showCounter();
    });
    $forward.on('click',function(){
    counterChange('+');
    $sliderList.trigger('counterChange');
    });
    $back.on('click',function(){
    counterChange('-');
    $sliderList.trigger('counterChange');
    });
    $(document.documentElement).on("keyup", function(event) {
    if(event.keyCode === 37) { //left arrow
    $back.trigger("click"); }
    else if (event.keyCode === 39) { //right arrow
    $forward.trigger("click"); }
    });
    //-----------------------------dom methods----------------------------
    function showCounter(){
    $counter.html(counter);
    }
    });
    };
    })(jQuery);
    当然,这个插件还远远不够成熟,理想状况下,给出容器元素,在对容器元素调用插件时传入图片url数列就可以实现slider功能,才算一个比较成熟的插件。这里只是提供一种组织代码思路。
    demo
  • 相关阅读:
    LeetCode> 989. 数组形式的整数加法
    Java> Java核心卷读书笔记
    npx是干嘛的
    typescript教程
    http Get 发送body数据
    59. 螺旋矩阵 II
    使用静态代理模式实现公用的报表导出功能
    win10更新后 sqlserver客户端连接一段时间后报错 CryptUnprotectData: Win32 错误:-2146893813 (Microsoft.SqlServer.RegSvrEnum)或该项不适用于在指定状态下使用
    Docker Compose-Window
    Docker的容器使用与连接-Window
  • 原文地址:https://www.cnblogs.com/imgss/p/6063914.html
Copyright © 2011-2022 走看看