【问题标题】:Making a slider without recursion制作没有递归的滑块
【发布时间】:2011-08-27 00:46:20
【问题描述】:

鉴于以下 jsFiddle,我如何在不构建堆栈的情况下实现与我所做的相同的效果?

http://jsfiddle.net/YWMcy/1/

我试着做这样的事情:

jQuery(document).ready(function () {
    'use strict';
    (function ($) {

        function validateOptions(options) {
            if (typeof(options.delay) == typeof(0)) {
                $.error('Delay value must an integer.');
                return false;
            } else if (options.delay < 0) {
                $.error('Delay value must be greater than zero.');
                return false;
            }

            if (typeof(options.direction) == typeof('')) {
                $.error('Direction value must be a string.');
                return false;
            } else if (!(options.direction in ['left', 'right', 'up', 'down'])) {
                $.error('Direction value must be "left", "right", "up", or "down".');
                return false;
            }

            if (typeof(options.easing) == typeof('')) {
                $.error('Easing value must be a string.');
                return false;
            }

            if (typeof(options.selector) == typeof('')) {
                $.error('Selector value must be a string.');
                return false;
            }

            if (options.transition < 0) {
                $.error('Transition value must be greater than zero.');
                return false;
            }
            return true;
        }

        var methods = {
            init:   function (options) {

                return this.each(function () {

                    var settings = {
                        delay:      5000,
                        direction:  'left',
                        easing:     'swing',
                        selector:   '*',
                        transition: 3000
                    };

                    if (options) {
                        $.extend(settings, options);
                    }

                    $(this).css({
                        overflow:   'hidden',
                        position:   'relative'
                    });

                    var styles = {
                        left:       0,
                        position:   'absolute',
                        top:        0
                    };

                    switch (settings.direction) {
                    case 'left':
                        styles.left = $(this).width() + 'px';
                        break;
                    case 'right':
                        styles.left = -$(this).width() + 'px';
                        break;
                    case 'up':
                        styles.top = $(this).height() + 'px';
                        break;
                    case 'down':
                        styles.top = -$(this).height() + 'px';
                        break;
                    default:
                        jQuery.error('Direction ' + settings.direction + ' is not valid for jQuery.fn.cycle');
                        break;
                    }

                    $(this).children(settings.selector).css(styles).first().css({
                        left:   0,
                        top:    0
                    });

                    if ($(this).children(settings.selector).length > 1) {
                        $(this).cycle('slide', settings);
                    }
                });
            },

            slide:  function (options) {
                return this.each(function () {

                    var settings = {
                        delay:      5000,
                        direction:  'left',
                        easing:     'swing',
                        selector:   '*',
                        transition: 3000
                    }, animation, property, value;

                    if (options) {
                        $.extend(settings, options);
                    }

                    switch (settings.direction) {
                    case 'left':
                        animation = {left: '-=' + $(this).width()};
                        property = 'left';
                        value = $(this).width();
                        break;
                    case 'right':
                        animation = {left: '+=' + $(this).width()};
                        property = 'left';
                        value = -$(this).width();
                        break;
                    case 'up':
                        animation = {top: '-=' + $(this).height()};
                        property = 'top';
                        value = $(this).height();
                        break;
                    case 'down':
                        animation = {top: '+=' + $(this).height()};
                        property = 'top';
                        value = -$(this).height();
                        break;
                    default:
                        jQuery.error('Direction ' + settings.direction + ' is not valid for jQuery.fn.cycle');
                        break;
                    }

                    $(this).children(settings.selector + ':first-child').each(function () {
                        $(this).delay(settings.delay);
                        $(this).animate(
                            animation,
                            settings.transition,
                            settings.easing,
                            function () {
                                $(this).css(property, value);
                            }
                        );
                    });

                    $(this).append($(this).children(settings.selector + ':first-child').detach());

                    $(this).children(settings.selector + ':first-child').each(function () {
                        $(this).delay(settings.delay);
                        $(this).animate(
                            animation,
                            settings.transition,
                            settings.easing,
                            function () {
                            $(this).parent().cycle('slide', settings);
                            }
                        );
                    });
                });
            }
        };

        jQuery.fn.cycle = function (method, options) {
            if (methods[method]) {
                return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
            } else if (typeof method === 'object' || !method) {
                return methods.init.apply(this, arguments);
            } else {
                $.error('Method ' + method + ' does not exist on jQuery.fn.cycle');
            }
        };
    }(jQuery));

    jQuery('.slider').cycle();

});

each() 方法不考虑循环期间添加的节点。

【问题讨论】:

  • 我还是不知道你到底想做什么?据我了解,如果滑块内只有一张幻灯片,您不想要幻灯片效果吗?然后只需检查 slider.children().length ?
  • 简单地说,我想让幻灯片循环播放。忘记我提到过关于何时可以/不能循环的任何规则。问题的重点是如何在不每次都向堆栈添加函数调用的情况下获得相同的效果。我想知道是否有某种方法可以使用while (true) 循环或类似的方法来实现它。

标签: javascript jquery slider


【解决方案1】:

您可以通过setInterval() 启动您的_cycle() 功能,以定期更新滑块:

setInterval(function() {
  _cycle2(slider, transition_duration, easing);
}, delay_duration);

请注意,我将您原来的 _cycle() 函数重命名为 _cycle2(),并删除了 delay_duration 参数。你可以see a working demo here

【讨论】:

  • 如果用户想使用setInterval() 做某事怎么办。根据我的经验,拥有多个 setInterval()s 的行为很奇怪。也许我做得不太对。但我无法停止这两个“间隔”。我只能停止最近设置的一个。
  • setInterval 返回一个您可以捕获的值。例如: my_interval = setInterval(function() { ... 如果您保存此值(即在全局范围内),您可以通过执行 clearInterval(my_interval) 轻松地仅停止此间隔。这只会停止(清除)此间隔,没有任何其他您或其他模块已启动。此处的示例:w3schools.com/jsref/met_win_clearinterval.asp
  • Tyler,这是您正在寻找的解决方案吗?如果不是,请解释原因。谢谢
  • 对不起,我没有忘记这件事。我现在真的很忙,所以我没有时间测试它。我明天或后天把它弄下来。非常感谢。
【解决方案2】:

你不想要任何类似于 while(true) 的东西。

您的问题源于您正在创建一个静态函数,然后试图弄清楚如何在将所有内容保持在静态函数范围内的约束下为子级设置动画。

您应该改为为每个元素创建一个对象的实例,让对象保持滑块的状态,并让它通过滑块运行所需的实现来更新该状态。

http://jsfiddle.net/qjVJF/3/

    (function ($) {
    var $b = $.behaviors || {};

    $b.slider = function(element, options) {
        this.element = $(element);
        this.panels = this.element.find('.slide');
        this.options = $.extend({}, $b.slider.defaults, options);

        this.currentPanel = 0;
        var horizontal = (this.options.direction == 'left' || this.options.direction == 'right');
        var anti = (this.options.direction == 'left' || this.options.direction == 'up');
        var distance  = horizontal ? '600' : '150';

        this.action = anti ? '-='+distance : '+='+distance;
        this.origin = anti ? distance : 0-distance;
        this.edge = horizontal ? 'left' : 'top';
        this.animation = horizontal ? { "left": this.action } : { "top" : this.action };

        this.panels.css(this.edge, this.origin+'px').show().first().css(this.edge, '0px');

        this.delayNext();
        return this;
    }
    $b.slider.defaults = {
        delay:      500,
        direction:  'left',
        easing:     'swing',
        transition: 3000
    };

    $b.slider.prototype = {
        delayNext: function() {
            setTimeout($.proxy(this.slideNext, this), this.options.delay);
        },
        slideNext: function() { 
            var current = this.panels[this.currentPanel % this.panels.length]; 
            var next = $(this.panels[++this.currentPanel % this.panels.length])
                .css(this.edge, this.origin+'px'); 

            var plugin = this;
            next.add(current).animate(
                this.animation,
                this.options.transition, 
                this.options.easing, 
                function() { 
                    if (this == current) plugin.delayNext();
                }
            );
        }  
    };

    $.fn.cycle = function (options) {
            return this.each(function() { 
                    $(this).data('bCycle', new $b.slider(this, options));
                });
    };
    }(jQuery));

    jQuery(document).ready(function () {
        jQuery('.slider').cycle();
    });

【讨论】:

  • 先生,您正在使用 JavaScript 和 jQuery 中的功能,这是我从未有过的新功能。太棒了。
【解决方案3】:

也许这个插件http://docs.jquery.com/Plugins/livequery可以帮到你?

Live Query 通过绑定事件或自动触发匹配元素的回调来利用 jQuery 选择器的强大功能,即使在页面已加载且 DOM 更新后也是如此。

例如,您可以使用以下代码将点击事件绑定到所有 A 标签,甚至是您可能通过 AJAX 添加的任何 A 标签。

    $('a') 
      .livequery('click', function(event) { 
        alert('clicked'); 
        return false; 
    }); 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-22
    • 2018-07-11
    • 2011-06-25
    • 2011-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-05
    相关资源
    最近更新 更多