1
votes

Is it possible to slow down the speed of a draggable element?

I have build a simple slider with jQuery drag and drop. When the slider element (the draggable element) moves to certain positions a picture fades in. So if you move the draggable element not too fast it looks like you can handle a "picture animation" with the slider. Now, I want to slow down the draggable element. So the user never can drag the element too fast.

This is an example of my code.

$('.slider').mousemove(function(){

 if($(this).position().left >= 0 && $(this).position().left <= 2 ) {
  $('.slider_1').fadeIn();
  $('.slider_2').fadeOut();
 }
...

I hope someone can help me :)

1

1 Answers

5
votes

Ah! finally an interesting jQuery question.

This can definitely be achieved. Below I've explained how. If you want to go straight to the demo, click here.


Let's assume your HTML is setup as follows:

<div id="slider">
    <div id="bar"></div>
</div>

Where the bar is the actual thing you click and drag.

Now what you need to do is the following:

  • get the $('#bar').offset().left
  • explicitly specify the position of #bar when the draggable is dragged, using some extra variable SPEED

For example:

ui.position.left += (ui.offset.left - ui.originalPosition.left - leftOffset)*SPEED;

Then, you can use the $('#bar').offset().left in jQuery's .fadeTo() (or other) function to change the opacity of the image you are talking about.

This all seems rather trivial, but it's not. There are some problems when trying to implement this. For example:

When the slider reaches the maximum sliding distance, it should stop animating or be reset. You can do this in multiple ways but I think the easiest solution is to write a .mousedown / .mouseup listener which updates a variable dragging, that keeps track whether the user is still trying to drag #bar. If it's not, reset #bar. If it is, keep the slider at the maximum distance until .mouseup is fired.

Also, you must be careful with predefined borders.

The code I propose is the following:

// Specify your variables here
var SPEED = -0.6;
var border = 1;           // specify border width that is used in CSS
var fadeSpeed = 0;        // specify the fading speed when moving the slider
var fadeSpeedBack = 500;  // specify the fading speed when the slider reverts back to the left

// Some pre-calculations
var dragging = false;
var slider = $('#slider');
var leftOffset = slider.offset().left + border;
var adjustedSliderWidth = 0.5*slider.width();

// the draggable function
$('#bar').draggable({
    axis: "x",
    revert : function(event, ui) {
            $(this).data("draggable").originalPosition = {
                top : 0,
                left : 0
            };
            $('#image').fadeTo(fadeSpeedBack, 0);
            return !event;
        },
    drag: function (event, ui) {
        var barOffset = $('#bar').offset().left - leftOffset;
        if (barOffset >= 0) {
            if (barOffset < adjustedSliderWidth) {
              ui.position.left += (ui.offset.left - ui.originalPosition.left - leftOffset)*SPEED;    
            } else {
              if (!dragging) { return false; } 
                else { ui.position.left = adjustedSliderWidth; }
            }
        }
        // fading while moving:
        $('#image').fadeTo(fadeSpeed, (ui.position.left/adjustedSliderWidth));
        
        // remove this if you don't want the information to show up:
        $('#image').html(ui.position.left/adjustedSliderWidth
                        +"<br \><br \>"
                        +ui.position.left);
    }
});

// the mouse listener
$("#bar").mousedown(function(){ dragging = true; });
$("#bar").mouseup(function(){ dragging = false; });

I've also implemented the revert option on draggable so the slider nicely returns to zero when the user releases #bar. Of course you can delete this if you want.

Now the variable that your whole question is about is the variable: SPEED.

You can specify the speed of dragging by specifying a number for this variable.

E.g.:

var SPEED = 0.0;         // the normal dragging speed
var SPEED = 0.5;         // the dragging speed is 1.5 times faster than normal
var SPEED = -0.5;        // the dragging speed is 0.5 times faster than normal

So negative values give a slower dragging speed and positive values give a faster dragging speed.

Unfortunately (or actually: fortunately), it is not possible to change the speed of the mouse pointer. This because only the OS has control over the mouse coordinates and speed. Browsers cannot influence this. Personally I think it doesn't matter: moving the slider slower than normal is what you're trying to achieve, so you can ignore the mouse pointer.


To see all this in action, I've prepared a working jsFiddle for you:

DEMO

I hope this helps you out :)