2

このjqueryを使用して、クリックするたびにdivを移動しました。

$(document).ready(function(){
    $('#hero').click(function(){
        $(this).animate({
            left: '+=50px'
    },300);
    })
})

純粋な JS に深く入り込むことが可能な場合はいつでも、jquery を避けたいと思います。

jqueryを使わずに同じ効果を達成する方法はありますか?

これがより複雑になることはわかっていますが、学ぼうとしているだけです。

4

4 に答える 4

1

数週間前、 vanilla-js.comでこの宝石を見つけました。

var s = document.getElementById('thing').style;
s.opacity = 1;
(function(){(s.opacity-=.1)<0?s.display="none":setTimeout(arguments.callee,40)})();

シンプルさとコードのサイズがとても気に入っています。エレガントで効率的!

left上記のコードに基づいて、選択した要素のプロパティに影響を与える関数を作成しました。

/* element: DOM element such as document.getElementById('hero')
   distance: distance in pixels to move to the left such as 50 or 100 */
function moveBy(element, distance){
    var target = isNaN(parseInt(s.left)) ? distance : parseInt(s.left) + distance;
    (function(){
        s.left = isNaN(parseInt(s.left)) ? '1px' : (parseInt(s.left) + 1).toString() + 'px';
        if(parseInt(s.left) <= distance) setTimeout(arguments.callee, 40);
    })();
}

試してみて、速度と滑らかさの点で好みに合ったものを確認できます。ここで jsfiddle で試してみてください

/* So you go: */
moveBy(document.getElementById('hero'), 50);
/* Or you can bind it to an event */
document.getElementById('hero').addEventListener('click', function(event){
    moveBy(this, 50);
});

このような解決策を改善したい場合に必要なのは、leftプロパティを に置き換えることtranslateです。ポール アイリッシュが彼のブログで述べているように、 (top-left-bottom-right) をtranslate使用して要素を移動するよりもはるかに優れたパフォーマンスが得られます。TRBL物事をスムーズにするために、ある種のイージング関数を追加することもできます。

于 2013-01-19T15:53:27.623 に答える
1

JavaScriptでも同じ手法を使用できます。

// get the object refrence
var hero_obj = document.getElementById('hero');

// attach the onclick event
hero_obj.onclick = function(){ 
    this.style.left = ( parseInt(this.style.left, 10) + 50 ) + 'px' 
};

ただし、効果はjqueryほどスムーズではありません

于 2013-01-19T12:44:42.843 に答える
1

これがアニメーション付きのコードです。このスニペットは最新のブラウザー専用ですが、古いブラウザー (IE) でも動作するように簡単に変更できます。(実際には、イベントの添付ファイルのみを修正する必要があります。)

window.onload = function () {
    var timer, k, intervals, kX, kY,
        counter = 0,
        hero = document.getElementById('hero'),
        posX = hero.offsetLeft,
        posY = hero.offsetTop,
        anim = function (elem, params) {
            posX += kX;
            posY += kY;
            elem.style.left = posX + 'px';
            elem.style.top = posY + 'px';
            if (counter > intervals) {
                clearInterval(timer);
                counter = 0;
            } else {
                counter++;
            }
            return;
        },
        move = function (elem, params) {
            if (timer) {
                clearInterval(timer);
                counter = 0;
            }
            k = Math.atan2(params.left, params.top);
            kX = Math.sin(k);
            kY = Math.cos(k);
            intervals = Math.floor(Math.sqrt(Math.pow(params.left, 2) + Math.pow(params.top, 2)));
            timer = setInterval(function () {
                anim(elem, params);
                return;
            }, params.speed);
            return;
        };
    document.getElementById('hero').addEventListener('click', function (e) {
        move(e.currentTarget, {left: 50, top: 0, speed: 0});
        return;
    }, false);
    return;
}

ご覧のとおり、このコードを使用すると、要素を垂直に移動して速度を調整することもできます。方向を切り替えるには-、対応するプロパティに追加するだけです。コードは単位としてのみピクセルを使用していますが、必要に応じて簡単に変更できます。

この機能コードをオブジェクトに変換するのも簡単です。また、jQuery のような期間は、params.duration代わりにプロパティを渡しparams.speed、それを使用して高度な計算を行うことkXで追加できますkY

jsFiddleでの動作デモ

于 2013-01-19T14:58:16.743 に答える
0

フレームワークを使用せずに、イージングでアニメーション ソリューションを作成する必要がありました。
私にとってトリッキーな部分は、アニメーションがユーザー インタラクションに関連付けられているときに、途中でアニメーションを中断/再開することに対処することでした。アニメーションが 2 回発生すると、すぐに問題が発生する可能性があることがわかりました。

これはgithubにあります:https://github.com/robCrawford/js-anim

いくつかのサポート機能がありますが、主なアニメーションは次のとおりです。

function animate(el, prop, to, pxPerSecond, easing, callback){
/**
* Animate style property
* i.e. animate(div1, "width", 1100, 1000, "out", function(){console.log('div1 anim end')});
* 
* @param el  DOM element
* @param prop  Property to animate
* @param to  Destination property value
* @param pxPerSecond  Speed of animation in pixels per second
* @param easing (optional)  Easing type: "in" or "out"
* @param callback (optional)  Function to call when animation is complete
*/
    var frameDur = 10,
        initPropVal = parseInt(getCurrCss(el, prop)),
        distance = Math.abs(to-initPropVal),
        easeVal = (easing==="in")?1.5:(easing==="out")?0.5:1, // >1 ease-in, <1 ease-out
        elAnimData = getData(el, 'animData');

    //Quit if already at 'to' val (still fire callback)
    if(initPropVal===to){
        if(callback)callback.call();
        return;
    }

    //Init animData for el if first anim
    if(!elAnimData){
        elAnimData = {};
        setData(el, {'animData':elAnimData});
    }

    //Get data for prop being animated or create entry
    var animDataOb = elAnimData[prop];
    if(!animDataOb)animDataOb = elAnimData[prop] = {};

    //Don't re-initialise an existing animation i.e. same prop/to
    if(animDataOb.to === to)return;
    animDataOb.to = to; //Store 'to' val

    //Clear any exisiting interval
    if(animDataOb.intId){
        clearInterval(animDataOb.intId);
        animDataOb.intId = null;
    }

    //Create new anim
    animDataOb.intId = (function(animDataOb){
        var totalSteps = Math.round((distance/pxPerSecond)/(frameDur*.001)),
            thisStep = 0;

        return setInterval(function(){
            var newVal = easeInOut(initPropVal, to, totalSteps, thisStep++, easeVal);
            if(!isNaN(newVal))el.style[prop] = newVal + "px"; //Allow 0
            if(thisStep > totalSteps)endAnim(animDataOb, callback);
        }, frameDur);
    })(animDataOb);
}

function endAnim(animDataOb, callback){
//End anim
    clearInterval(animDataOb.intId);
    animDataOb.intId = animDataOb.to = null;
    if(callback)callback.call();
}
于 2013-01-19T17:25:23.160 に答える