我花了最后6个小时试图找到问题的答案,但没有任何运气。
我的网站上有一些可拖动的div。当我拖动它们时,我想要一个逼真的效果,就像有一个气压而且它们被推了一下,所以当它们被拖动时它们会摆动一点。
效果如何起作用的示例图像可以在这里看到:The inertia acceleration effect(不知道效果是什么)
我用许多不同的组合搜索这些单词“Javascript,加速度,惯性,摆动,物理,旋转,移动,气压,摩擦,悬挂”,但没有找到任何帮助我的东西。
虽然,我在这个JSFiddle上发现了一种类似的效果[1](链接如下)。我还遇到了Google Gravity [2](下面的链接),当你拖动一个元素并将鼠标移到一边时,它具有我想要实现的效果。
[1] JSFiddle我发现:www.jsfiddle.net/gVCWE/150 /
[2] Google Gravity:www.mrdoob.com/projects/chromeexperiments/google-gravity /
我试图在这里自己创造效果:
var fn = {
activeElm : null,
pos : {},
transPos : {},
startPos : null,
moveSteps : new Array(15),
init : function(){
var self = this;
document.addEventListener('mousedown', function(e){self.handleStart.call(self, e);});
document.addEventListener('mousemove', function(e){self.handleMove.call(self, e);});
document.addEventListener('mouseup', function(e){self.handleStop.call(self, e);});
},
handleStart : function(e){
if(fn.hasClass('dragme', e.target)){
fn.activeElm = e.target;
e.preventDefault();
fn.startPos = {x : e.pageX, y : e.pageY};
var lastPos = {x : fn.activeElm.getAttribute('data-posX'), y : fn.activeElm.getAttribute('data-posY')};
if(lastPos['x'] && lastPos['y']){
fn.transPos = {x : parseFloat(lastPos['x']), y : parseFloat(lastPos['y'])};
}else{
fn.transPos = {x : 0, y : 0};
}
fn.pos = {x : fn.transPos['x'], y : fn.transPos['y']};
fn.loop();
}
},
handleMove : function(e){
if(!fn.activeElm)
return;
fn.pos = {x : fn.transPos['x'] + e.pageX - fn.startPos['x'], y : fn.transPos['y'] + e.pageY - fn.startPos['y']};
},
handleStop : function(e){
if(!fn.activeElm)
return;
fn.activeElm.setAttribute('data-posX', fn.pos['x']);
fn.activeElm.setAttribute('data-posY', fn.pos['y']);
fn.activeElm = null;
},
addStep : function(move){
var arr = fn.moveSteps;
arr = arr.slice(1, arr.length);
arr.push(move);
fn.moveSteps = arr;
},
loop : function(){
if(!fn.activeElm)
return false;
fn.requestAnimFrame(fn.loop);
fn.addStep(fn.pos['x']);
fn.animate();
},
animate : function(){
var arr = fn.moveSteps;
var rotaSpeed = arr[arr.length-1] - arr[0];
// The Math.min- and max are there, so we can be sure the angle won't rotate more than 90° and -90°
var rotation = 'rotate(' + Math.max(Math.min(90, rotaSpeed), -90) + 'deg)';
if(!fn.activeElm)
return;
var obj = fn.activeElm.parentNode.style;
obj.webkitTransform = obj.MozTransform = obj.msTransform = obj.OTransform = obj.transform = 'translate(' + fn.pos['x'] + 'px, ' + fn.pos['y'] + 'px) ' + rotation;
},
requestAnimFrame : function(callback){
return window.requestAnimationFrame && window.requestAnimationFrame(callback) ||
window.webkitRequestAnimationFrame && window.webkitRequestAnimationFrame(callback) ||
window.mozRequestAnimationFrame && window.mozRequestAnimationFrame(callback) ||
window.oRequestAnimationFrame && window.mozRequestAnimationFrame(callback) ||
window.msRequestAnimationFrame && window.msRequestAnimationFrame(callback) ||
window.setTimeout(callback, 1000 / 60);
},
hasClass : function(classname, obj){
return new RegExp(' ' + classname + ' ').test(' ' + obj.className + ' ');
}
}
fn.init();
但结果看起来并不现实,尤其是当您快速移动鼠标时。我认为需要函数Math.sin来使旋转中更加逼真的“缓动”,因为div会移动。 我不知道如何计算这个物理,所以如果有人有想法,来源,例子,公式,什么或者只知道效果的名称那就太棒了。
//祝你好运
答案 0 :(得分:1)
您正在寻找2D Rigid Body Dynamics。
考虑使用物理引擎以更少的努力和更好的结果来实现您想要的效果。
请注意,Google Gravity使用Box2Djs,一个物理引擎,Box2DFlash到JavaScript的端口。如果您查看页面的代码,您将找到如何正确设置Box2djs。
使用Box2d,您将能够设置世界和物体属性(如重力,摩擦力)和其他物理属性。
下面是Google Gravity中出现的代码示例,用于处理Box2d:
// init box2d
worldAABB = new b2AABB();
worldAABB.minVertex.Set(-200, -200);
worldAABB.maxVertex.Set(window.innerWidth + 200, window.innerHeight + 200);
world = new b2World(worldAABB, new b2Vec2(0, 0), true);
// Get box2d elements
elements = getElementsByClass("box2d");
for (var i = 0; i < elements.length; i++) {
properties[i] = getElementProperties(elements[i]);
}
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
element.style.position = 'absolute';
element.style.left = properties[i][0] + 'px';
element.style.top = properties[i][1] + 'px';
element.style.width = properties[i][2] + 'px';
element.addEventListener('mousedown', onElementMouseDown, false);
element.addEventListener('mouseup', onElementMouseUp, false);
element.addEventListener('click', onElementClick, false);
bodies[i] = createBox(world, properties[i][0] + (properties[i][2] >> 1), properties[i][1] + (properties[i][3] >> 1), properties[i][2] / 2, properties[i][3] / 2, false);
// Clean position dependencies
while (element.offsetParent) {
element = element.offsetParent;
element.style.position = 'static';
}
}
这段代码只是为了帮助您找到重要的代码。仔细研究Google Gravity的代码,了解如何使用Box2djs创建所需的效果。
如果您决定使用物理引擎,您可能更喜欢Box2dWeb而不是Box2Djs,因为它已更新并存储在单个js文件中。
自己实施realist effect
很难,而不仅仅是简单地使用正弦或余弦。也许有一些视觉上类似的效果,但同样,如果不应用良好的物理模拟,现实效果就更难实现。
2D Rigid Body Dynamics - 麻省理工学院开放式课程
答案 1 :(得分:1)
在没有任何真实模拟的情况下,我做了一些可自定义的事情,以最后2次移动的速度来设置div的角度。
this.drag = function (elem, e) {
//
//ROTATION
//
//If there's an end animation I kill it.
endAnimation.stop();
//Saving the mouse position
history.push(e);
//When we have positions to compare
if(history.length > 1){
if (history.length > 2) {
history.shift();
}
var dX = history[0].clientX - history[1].clientX; // Delta
var tAngle = Math.ceil(angle * -dX); // Angle to reach
var rotation = 'rotate('+ tAngle +'deg)';
$(elem).css({WebkitTransform: rotation});
$(elem).css({'-moz-transform': rotation});
$(elem).css({transform: rotation});
}
}
使用它,您可以更改角度变量以增大或减小角度。
我还使用另一个topic
添加了一些惯性您可以在此处查看结果http://jsfiddle.net/Spope/tzqwx/