2

我使用这个 jquery 通过每次点击来移动一个 div。

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

只要有可能更深入地了解纯 JS,我就想避免使用 jquery。

无论如何不使用jquery也能达到同样的效果吗?

我知道这会更复杂,但只是尝试学习。

4

4 回答 4

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;
}

如您所见,使用此代码,您还可以垂直移动元素并调整速度。要切换方向,只需添加-到相应的属性。该代码仅使用像素作为单位,但如果需要,很容易修改。

将此功能代码转换为对象也很容易。也可以通过传递属性params.duration而不是使用params.speedand 进行一些高级计算kX来添加类似 jQuery 的持续时间kY

在jsFiddle工作演示

于 2013-01-19T14:58:16.743 回答
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. 正如Paul Irish 在他的博客中所说,提供比使用(top-left-bottom-right)translate移动元素更好的性能。TRBL也可以添加某种缓动功能以使事情变得顺畅。

于 2013-01-19T15:53:27.623 回答
0

我需要在不使用框架的情况下创建一个动画解决方案。
对我来说,棘手的部分是处理与用户交互相关的中断/重新启动动画。我发现如果你的动画双发,你很快就会遇到麻烦。

这是在 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 回答