1

過去 6 時間、質問に対する答えを見つけようとしましたが、運がありませんでした。

Web サイトにドラッグ可能な div がいくつかあります。ドラッグしている間は、空気圧がかかって少し押されるようなリアルな効果が欲しいので、ドラッグすると少し揺れます。

効果がどのように機能するかの例の画像は、ここで見ることができます:慣性加速効果(効果が何と呼ばれるかわかりません)

これらの単語をさまざまな組み合わせで「Javascript、加速度、慣性、スイング、物理学、回転、移動、空気圧、摩擦、ぶら下がり」で検索しましたが、何も見つかりませんでした。

ただし、この JSFiddle[ 1 ] にも同様の効果があることがわかりました (以下のリンク)。また、要素をドラッグしてマウスを横に移動すると、実現したい効果がある Google Gravity[2] (以下のリンク) にも出会いました。

[ 1 ] 私が見つけた JSFiddle: www.jsfiddle.net/gVCWE/150/

[ 2 ] Google 重力: 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デモ

  • 私がすること: 過去 15 回のマウスの移動中にマウスがどれだけ移動したかを計算し、回転角度をその値に設定します。そのため、マウスが速く動くと、15 回のマウスの動きの間のスパンが大きくなり、ボックスの回転が大きくなります。マウスがゆっくり動くと、スパンが小さくなり、ボックスの回転が以前ほど大きくなくなります。

ただし、特にマウスを速く動かしている場合は、結果がリアルに見えません。関数 Math.sin は、div が移動するときに回転をより現実的に「容易にする」ために必要だと思います。この物理を計算する方法がわからないので、アイデア、情報源、例、式など、効果の名前を知っている人がいれば、それは素晴らしいことです.

//よろしくお願いします

4

2 に答える 2

1

2D Rigid Body Dynamicsを探しています。

物理エンジンを使用して、はるかに少ない労力で優れた結果で目的の効果を達成することを検討してください。

Google Gravityは、 Box2DFlashを JavaScript に移植した物理エンジンである Box2Djs を使用していることに注意してください。ページのコードを見ると、Box2djs を適切にセットアップする方法がわかります。

Box2d を使用すると、世界とオブジェクトのプロパティ (重力、摩擦など) およびその他の物理プロパティを設定できます。

Box2d を処理するために Google Gravity に存在するコードのサンプルを次に示します。

// 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 を使用して目的の効果を作成する方法を学びます。

物理エンジンを使用する場合は、Box2Djsではなく Box2dWeb を使用することをお勧めします。これは、単一の js ファイルに更新および格納されるためです。

を独自に実装するrealist effectのは難しく、サインやコサインを単純に使用するだけでは不十分です。視覚的に似たような効果があるかもしれませんが、現実的な効果は、適切な物理シミュレーションを適用しないと達成するのが難しくなります。

2D リジッド ボディ ダイナミクス- MIT OpenCourseWare

于 2013-05-24T00:35:14.817 に答える
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});
    }
}

これにより、角度変数を変更して角度を増減できます。

また、別のトピックを使用して、ドロップ時に慣性を追加しました

ここで結果を見ることができますhttp://jsfiddle.net/Spope/tzqwx/

于 2013-08-09T09:36:08.903 に答える