使用jquery ui draggable(http://jqueryui.com/demos/draggable/)拖动元素时如何启用缓动或惯性?我想重新创建类似于maps.google.com的缓动,当您抛出/拖动地图时,它会轻松到位。理想情况下,我想根据您投掷/拖动元素的力移动元素移动。你是如何完成这项功能的?也许jquery ui draggable不是必需的,但我希望模仿谷歌地图上的拖动和缓和。
谢谢!
答案 0 :(得分:21)
我使用了here中的一些想法,但是将它们与jQuery UI集成在一起。你必须实现逻辑来处理一个动量动画,它将元素推出越界(在它的父容器的边界之外)
结果代码:
$(function() {
var $d = $("#draggable");
var x1, x2,
y1, y2,
t1, t2; // Time
var minDistance = 40; // Minimum px distance object must be dragged to enable momentum.
var onMouseMove = function(e) {
var mouseEvents = $d.data("mouseEvents");
if (e.timeStamp - mouseEvents[mouseEvents.length-1].timeStamp > 40) {
mouseEvents.push(e);
if (mouseEvents.length > 2) {
mouseEvents.shift();
}
}
}
var onMouseUp = function() {
$(document).unbind("mousemove mouseup");
}
$d.draggable({
start: function(e, ui) {
$d.data("mouseEvents", [e]);
$(document)
.mousemove(onMouseMove)
.mouseup(onMouseUp);
},
stop: function(e, ui) {
$d.stop();
$d.css("text-indent", 100);
var lastE = $d.data("mouseEvents").shift();
x1 = lastE.pageX;
y1 = lastE.pageY;
t1 = lastE.timeStamp;
x2 = e.pageX;
y2 = e.pageY;
t2 = e.timeStamp;
// Deltas
var dX = x2 - x1,
dY = y2 - y1,
dMs = Math.max(t2 - t1, 1);
// Speeds
var speedX = Math.max(Math.min(dX/dMs, 1), -1),
speedY = Math.max(Math.min(dY/dMs, 1), -1);
// Distance moved (Euclidean distance)
var distance = Math.sqrt(Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2));
if (distance > minDistance) {
// Momentum
var lastStepTime = new Date();
$d.animate({ textIndent: 0 }, {
duration: Math.max(Math.abs(speedX), Math.abs(speedY)) * 2000,
step: function(currentStep){
speedX *= (currentStep / 100);
speedY *= (currentStep / 100);
var now = new Date();
var stepDuration = now.getTime() - lastStepTime.getTime();
lastStepTime = now;
var position = $d.position();
var newLeft = (position.left + (speedX * stepDuration / 4)),
newTop = (position.top + (speedY * stepDuration / 4));
$d.css({
left: newLeft+"px",
top: newTop+"px"
});
}
});
}
}
});
});
答案 1 :(得分:9)
simshaun所做的工作非常棒。
我搞砸了他的版本,并使用jquery.easing插件获得了更平滑的动画 试试jsfiddle。
$(document).ready(function() {
$('#dragme').draggable({
start: function(e, ui) {
dragMomentum.start(this.id, e.clientX, e.clientY, e.timeStamp);
},
stop: function(e, ui) {
dragMomentum.end(this.id, e.clientX, e.clientY, e.timeStamp);
}
});
});
var dragMomentum = new function () {
var howMuch = 30; // change this for greater or lesser momentum
var minDrift = 6; // minimum drift after a drag move
var easeType = 'easeOutBack';
// This easing type requires the plugin:
// jquery.easing.1.3.js http://gsgd.co.uk/sandbox/jquery/easing/
var dXa =[0];
var dYa =[0];
var dTa =[0];
this.start = function (elemId, Xa, Ya, Ta) {
dXa[elemId] = Xa;
dYa[elemId] = Ya;
dTa[elemId] = Ta;
}; // END dragmomentum.start()
this.end = function (elemId, Xb, Yb, Tb) {
var Xa = dXa[elemId];
var Ya = dYa[elemId];
var Ta = dTa[elemId];
var Xc = 0;
var Yc = 0;
var dDist = Math.sqrt(Math.pow(Xa-Xb, 2) + Math.pow(Ya-Yb, 2));
var dTime = Tb - Ta;
var dSpeed = dDist / dTime;
dSpeed=Math.round(dSpeed*100)/100;
var distX = Math.abs(Xa - Xb);
var distY = Math.abs(Ya - Yb);
var dVelX = (minDrift+(Math.round(distX*dSpeed*howMuch / (distX+distY))));
var dVelY = (minDrift+(Math.round(distY*dSpeed*howMuch / (distX+distY))));
var position = $('#'+elemId).position();
var locX = position.left;
var locY = position.top;
if ( Xa > Xb ){ // we are moving left
Xc = locX - dVelX;
} else { // we are moving right
Xc = locX + dVelX;
}
if ( Ya > Yb ){ // we are moving up
Yc = (locY - dVelY);
} else { // we are moving down
Yc = (locY + dVelY);
}
var newLocX = Xc + 'px';
var newLocY = Yc + 'px';
$('#'+elemId).animate({ left:newLocX, top:newLocY }, 700, easeType );
}; // END dragmomentum.end()
}; // END dragMomentum()