#1
  1. JavaScript is not spelt java
    Devshed Novice (500 - 999 posts)

    Join Date
    Feb 2011
    Location
    Landan, England
    Posts
    743
    Rep Power
    165

    Carousel judders


    My code below for an image carousel works fine. It scrolls a sequence of images to the left or right and I can specify the total duration (for all images to have scrolled) and an increment - the number of pixels to move each time.

    However, there is a very slight judder or pause which seems to happen around every 10th movement. Does anyone have an idea why this might be? I'm not expecting anyone to study the code in detail, but am hoping that someone may have experienced something similar in the past.

    Might it be related to my use of setTimeout rather than setInterval? Or perhaps I should make my calculations more efficient? Andy.

    Code:
    function Carousel(obj) {
            if (!(this instanceof Carousel)) return new Carousel(obj);
            // ..did they use "new"?
            if ( !obj.objID ) {
                throw new Error("Element id is required.");
            }
            this.theObj = adg.$(obj.objID);
            if ( !this.theObj ) {
                throw new Error("The element doesn\'t exist.");
            }
            if ( adg.GetStyle(this.theObj,'position').toLowerCase() == 'static' )
                throw new Error("Must be a positioned element.");
            this.objWidth = parseInt(adg.GetStyle(this.theObj,'width'),10);
            this.conWidth = parseInt(adg.GetStyle(this.theObj.parentNode,'width'),10);
            if ( this.objWidth <= this.conWidth ) {
                throw new Error("Element must be wider than it\'s container.");
            }
            this.lft = parseInt(adg.GetStyle(this.theObj,'left'),10);
            this.lft = isNaN(this.lft) ? 0 : this.lft;   // IE/Chrome return 'auto'
            this.inc = ( obj.inc ) ? obj.inc : 1;       // pixels to move per interval
            this.gap = ( obj.duration ) ? (obj.duration / (this.objWidth - this.conWidth)) : 30;
            // ..defaults to 30ms intervals
    
            var that = this;    // preserve scope
            if ( obj.bLeft ) adg.AddEvent(adg.$(obj.bLeft),'click',function(e) {
                return that.MoveIt(true);   // true = move to left
            });
            if ( obj.bRight ) adg.AddEvent(adg.$(obj.bRight),'click',function(e) {
                return that.MoveIt(false);  // false = move to right
            });
            if ( obj.bToggle ) adg.AddEvent(adg.$(obj.bToggle),'click',function(e) {
                return that.ToggleMove();
            });
            return this;
        }
        Carousel.prototype = {
            constructor : Carousel,     // otherwise it inherits Object.prototype
            CancelMove : function () {
                clearTimeout(this.theTimer);
                this.Moving = false;     // -inc = left, +inc = right
            },
            MoveIt : function (blnLeft) {  // blnLeft : true = left, false = right
                var MoveToLeft = function (blnLeft) {          // called by MoveIt()
                    if ( blnLeft && (this.lft + this.objWidth >= this.conWidth + this.inc) ) {
                        this.lft -= this.inc;
                    }
                    else if ( !blnLeft && (this.lft <= -this.inc) ) {
                        this.lft += this.inc;
                    }
                    else {
                        this.Moving = false;
                        return false;
                    }
                    this.theObj.style.left = this.lft + 'px';
                    var that = this;    // preserve scope
                    this.theTimer = setTimeout(function () {
                        MoveToLeft.call(that, blnLeft);
                    }, that.gap);
                    return true;
                };
                if ( this.Moving ) {
                    this.CancelMove();
                } else {
                    this.Moving = ( blnLeft ) ? -this.inc : this.inc;
                    MoveToLeft.call(this,blnLeft);
                }
            },
            ToggleMove : function () {
                var ml = this.Moving;       // was it moving already?
                this.CancelMove();
                if ( this.lft ) {
                    ( ml > 0 ) ? this.MoveIt(true) : this.MoveIt(false);
                } else {        // it's already furthest right..
                    this.MoveIt(true);      // so move it left
                }
            }
        };
  2. #2
  3. JavaScript is not spelt java
    Devshed Novice (500 - 999 posts)

    Join Date
    Feb 2011
    Location
    Landan, England
    Posts
    743
    Rep Power
    165
    It's at the bottom of this page.
  4. #3
  5. JavaScript is not spelt java
    Devshed Novice (500 - 999 posts)

    Join Date
    Feb 2011
    Location
    Landan, England
    Posts
    743
    Rep Power
    165
    Well I'm on broadband, so perhaps if someone can just confirm if the scrolling-action is acceptable to them
  6. #4
  7. No Profile Picture
    Super Moderator
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jul 2003
    Posts
    4,008
    Rep Power
    2791
    I think it is more a need of interval:pixel tweaking than anything else. jsMorph have some nice timings that you could take a look at for numbers.
    [PHP] | [Perl] | [Python] | [Java] != [JavaScript] | [XML] | [ANSI C] | [C++] | [LUA] | [MySQL] | [FirebirdSQL] | [PostgreSQL] | [HTML] | [XHTML] | [CSS]

    W3Fools - A W3Schools Intervention.
  8. #5
  9. JavaScript is not spelt java
    Devshed Novice (500 - 999 posts)

    Join Date
    Feb 2011
    Location
    Landan, England
    Posts
    743
    Rep Power
    165
    Originally Posted by Winters
    I think it is more a need of interval:pixel tweaking than anything else. jsMorph have some nice timings that you could take a look at for numbers.
    Thank you, Andy.
  10. #6
  11. JavaScript is not spelt java
    Devshed Novice (500 - 999 posts)

    Join Date
    Feb 2011
    Location
    Landan, England
    Posts
    743
    Rep Power
    165
    I want to pursue this a little more as tweaking the timer interval and/or duration doesn't completely fix the flicker.

    Is it preferable to change the right/left setting of an element or the right or left-margin?
    Is setInterval preferable to setTimeout in terms of performance/behaviour? (I'm currrently re-setting setTimeout on each iteration.)

    I'm still talking about a linear transition and understand that a non-linear slide (or morph) would probably improve the effect.

IMN logo majestic logo threadwatch logo seochat tools logo