惯性/气压使div移动/拖动时摆动/旋转div

问题描述 投票:1回答:2

我花了最后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();

JSFiddle Demo

  • 我的工作:我计算鼠标最后15次移动时鼠标移动了多少,然后将旋转度设置为该值。因此,当鼠标快速移动时,这15个鼠标移动之间的跨度将变大,因此框旋转也会变大。当鼠标缓慢移动时,跨度将变小,并且框旋转将不会像以前那样大。

但是结果看起来并不真实,尤其是当您快速移动鼠标时。我认为,随着div的移动,需要使用Math.sin函数来使旋转更加逼真。我不知道如何计算这个物理学,因此,如果有人有一个主意,来源,示例,公式,无论有什么或只是知道影响的名称,那将是很棒的。

//最诚挚的问候

javascript physics drag mousemove
2个回答
1
投票

您正在寻找2D Rigid Body Dynamics

考虑使用物理引擎以更少的努力和出色的效果来实现所需的效果。

注意Google Gravity使用Box2DFlash的JavaScript物理引擎Box2Djs。如果您查看该页面的代码,则会发现如何正确设置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-MIT OpenCourseWare


1
投票

[没有任何真实的模拟,我做了一些可自定义的操作,以最后两个动作的速度来设置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/

© www.soinside.com 2019 - 2024. All rights reserved.