5
\$\begingroup\$

I have two instances of this carousel to test with, one with 7 slides and the other with 25. They run the exact same code. The 7 slide instance drags smoothly forever as intended, but the 25 slide instance is choppy when dragging.

Something in the dragMove event is slowing down execution when the slide count is higher, and I'd like to find a way to improve it so that the slide count has no effect on performance.

I've already tried a few optimizations, like replacing:

$slider.children().last()

with

$Slider[0].lastChild

To bypass instantiating of all those unnecessary Jquery objects just to get the last one, but dragging is still choppy.

Here's the dragMove event:

function dragMove(event){
  var ev = event.originalEvent || event || window.event;      
  var MousePosition = GetEventCoordinates(ev);      
  var MouseMoveDistance = (MousePosition.x-locals.StartingMousePosition.x);
  var DistanceDifference = (locals.LastMouseMoveDistance-MouseMoveDistance);
  var MoveDirection = (DistanceDifference === 0 || isNaN(DistanceDifference)) ? locals.LastMoveDirection : (DistanceDifference>0) ? '<' : '>' ; // negative to the left
  var StepsMoved = Math.floor(MouseMoveDistance/base.protected.ItemWidth);
  var StepsDifference = (locals.LastStepsMoved-StepsMoved);

  if(StepsDifference !== 0 || locals.LastMoveDirection !== MoveDirection){
     // Steps has changed, recalculate!
     var oEdgeCounts = base.GetEdgeCounts();

     if(oEdgeCounts.left<1 && MoveDirection==='>'){
        // There are non to the left, but we need some!
        if(StepsDifference===0){StepsDifference=1;}
        for(var i=0; i<Math.abs(StepsDifference); i++){               
           $Last = $(base.protected.$Slider[0].lastChild);
           base.protected.$Slider.prepend($Last);
        }
        locals.PopAdjustment = (locals.PopAdjustment+(Math.abs(StepsDifference)*base.protected.ItemWidth));
     }

     if(oEdgeCounts.right<1 && MoveDirection==='<'){
        //There are none to the right, but we need some!
        if(StepsDifference===0)StepsDifference=1;
        for(var i=0; i<Math.abs(StepsDifference); i++){               
           $First = $(base.protected.$Slider[0].firstChild);
           base.protected.$Slider.append($First);
        }
        locals.PopAdjustment = (locals.PopAdjustment-(Math.abs(StepsDifference)*base.protected.ItemWidth));
     }
  }      

  locals.NewSliderLeft = GetEventCoordinates(ev).x - locals.DragStartTouchOffsetX-locals.PopAdjustment;      

  // Save values so we can compare on next event      
  locals.LastSampleMousePosition = MousePosition;
  locals.LastMouseMoveDistance = MouseMoveDistance;
  locals.LastMoveDirection = MoveDirection;
  locals.LastStepsMoved = StepsMoved;

  base.protected.$Slider.css('left',locals.NewSliderLeft);
}

Here is the get Edge count function. It uses simple math to determin the number of slides off the left and off the right sides. I don't think it's speed is impacted by slide count.

GetEdgeCounts = function(){       
   var base = this;       
   var SliderLeft = parseInt(base.protected.$Slider.css('left'),10);
   var OffLeftCount = Math.abs(SliderLeft)/base.protected.ItemWidth;
   var OffLeftFloor = Math.floor(OffLeftCount);
   var OffRightCount = base.protected.TotalItems-base.protected.ItemsPerPage-OffLeftCount;
   var OffRightFloor = Math.floor(OffRightCount);

   OffRightFloor = (OffRightFloor >=0) ? OffRightFloor : 0;
   OffLeftFloor = (OffLeftFloor >=0) ? OffLeftFloor : 0;
   return{
      left:OffLeftFloor,
      right:OffRightFloor,
      center:base.protected.ItemsPerPage
   };
}

I'm looking for any ideas on how to make dragging with larger slide counts less choppy.

\$\endgroup\$
2
  • \$\begingroup\$ can you add an operational fiddle for this at jsfiddle.net or give a Github repo? I want to see the DOM as well \$\endgroup\$
    – netpoetica
    Commented Oct 21, 2014 at 0:13
  • 1
    \$\begingroup\$ Chrome's timeline and profiler will help you figure out what is taking so much time. Activate the debugger, go to timeline, click the red circle to record, make your choppy drag happen, and stop the record by clicking the red circle again. Zoom into the timeline around the part where you did the drag and look for the widest bar(s). Mouse over it and it will tell you what it was doing. Let us know what you find is the time consumer, if you try this. \$\endgroup\$
    – Doug Gale
    Commented Nov 5, 2014 at 18:49

1 Answer 1

3
\$\begingroup\$

From a once over, some performance tips:

  • At least on some versions of Chrome, parseInt(string,10); is slower than a number of alternatives, my preference is +string
  • It is faster to call Math.abs(string) than Math.abs(parseInt(string,10))
  • Each object property lookup has a cost, so consider var base = this.protected; since all your object accesses are on `base.protected'
  • Be wary of ternary operators, a regular if tends to be faster
  • Your code has actually a number of little inefficiencies
    • You will capture var MousePosition = GetEventCoordinates(ev); but then later you still call locals.NewSliderLeft = GetEventCoordinates(ev).x - locals.DragStartTouchOffsetX-locals.PopAdjustment;
    • You store locals.NewSliderLeft but you use it only once in the assignment here: base.protected.$Slider.css('left',locals.NewSliderLeft);, I would skip storing this value in locals altogether.
  • From a style perspective, I would suggest that you use more spaces and fewer parentheses so var MouseMoveDistance = (MousePosition.x-locals.StartingMousePosition.x); becomes
    var MouseMoveDistance = MousePosition.x - locals.StartingMousePosition.x;
  • Also prefixing in general is discouraged (oEdgeCounts)
  • From a DRY perspective, the block of if(oEdgeCounts.left<1 && MoveDirection==='>'){ and if(oEdgeCounts.right<1 && MoveDirection==='<'){ is pretty much copy pasted, you should refactor that

All in all, your code is quite readable and maintainable and I dont see immediately where the culprit is. I fully endorse the opion of Doug Gale to use the Chrome developer tools to find the culprit.

\$\endgroup\$
2
  • \$\begingroup\$ On FF 30, Bitwise >> (right shift) and Multiply (force cast) were the fastest with the plus operator running slower than parseInt(). \$\endgroup\$
    – Nick
    Commented Dec 11, 2014 at 13:25
  • \$\begingroup\$ Hah, go figure.. \$\endgroup\$
    – konijn
    Commented Dec 11, 2014 at 13:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.