JS消失的财产

时间:2014-03-09 03:08:49

标签: javascript object properties undefined

/*jslint browser: true, devel: true */
//*********************** Constants **************************
var FPS = 30;

var ANIMATIONOBJECTX = 1;
var ANIMATIONOBJECTY = 2;
var ANIMATIONOBJECTOPACITY = 3;
var ANIMATIONOBJECTWIDTH = 4;
var ANIMATIONOBJECTHEIGHT = 5;
var ANIMATIONOBJECTROTATION = 6;

//*********************** Rotation **************************

function setRotation(view, angle) {
    "use strict";
    view.css({
        "-webkit-transform" : "rotate(" + angle + "deg)",
        "-moz-transform" : "rotate(" + angle + "deg)",
        "-ms-transform" : "rotate(" + angle + "deg)",
        "-o-transform" : "rotate(" + angle + "deg)",
        "transform" : "rotate(" + angle + "deg)"
    });

    view.angle = angle; //For getting the angle later
}

//*********************** Classes **************************

var AnimationObject = function (start, end, time, isSmooth, type, object) {
    "use strict";
    this.type = type;
    this.stages = [];

    var dif = end - start,
        a,
        b,
        steps = time * FPS;

    if (isSmooth) {
        for (a = 0; a < steps; a += 1) {
            if (a <= steps / 2) {
                //Normal parabola
                b = (2.0 / 9) * Math.pow(a, 2) * Math.pow(1.0 / time, 2);
            } else {
                //Upside down parabola
                b = (-2.0 / 9) * Math.pow(a - (FPS * time), 2) * Math.pow(1.0 / time, 2) + 100;
            }

            this.stages.push(b / 100 * dif + start);
        }
    } else {
        for (a = 0; a < steps; a += 1) {
            this.stages.push(a / steps * dif + start);
        }
    }

    //Applies animation value differently depending on type
    if (type === ANIMATIONOBJECTX) {
        this.applyAnimation = function (step) {
            object.css("left", this.stages[step]);
        };
    } else if (type === ANIMATIONOBJECTY) {
        this.applyAnimation = function (step) {
            object.css("top", this.stages[step]);
        };
    } else if (type === ANIMATIONOBJECTOPACITY) {
        this.applyAnimation = function (step) {
            object.css("opacity", this.stages[step]);
        };
    } else if (type === ANIMATIONOBJECTWIDTH) {
        this.applyAnimation = function (step) {
            object.css("width", this.stages[step]);
        };
    } else if (type === ANIMATIONOBJECTHEIGHT) {
        this.applyAnimation = function (step) {
            object.css("height", this.stages[step]);
        };
    } else if (type === ANIMATIONOBJECTROTATION) {
        this.applyAnimation = function (step) {
            setRotation(object, this.stages[step]);
        };
    }
};

var AnimationManager = function (time, completionMethod) {
    "use strict";
    this.animationObjects = [];
    this.time = time;
    this.add = function (animationObject) {
        this.animationObjects.push(animationObject);
    };
    this.completionMethod = completionMethod;
    this.currentStage = 0;
    this.maximumStage = this.time * FPS;

    this.tick = function () {
        this.currentStage += 1;
        if (this.currentStage < this.maximumStage) {
            setTimeout(this.tick.bind(this), 1000.0 / FPS);
        } else {
            //Set manager to nil in the completion method
            this.completionMethod();
        }

        var i;
        for (i = 0; i < this.animationObjects.length; i += 1) {
            this.animationObjects[i].applyAnimation(this.currentStage);

        }
    };

    //Call this to start
    this.startAnimation = function () {
        this.timer = setTimeout(this.tick.bind(this), 1000.0 / FPS);
    };
};

//*********************** Animate Objects **************************
function animatePosition(object, manager, x, y, smooth) {
    "use strict";
    var curX = parseFloat(object.position().left),
        curY = parseFloat(object.position().top);

    manager.add(
        new AnimationObject(curX, x, manager.time, smooth, ANIMATIONOBJECTX, object)
    );
    manager.add(
        new AnimationObject(curY, y, manager.time, smooth, ANIMATIONOBJECTY, object)
    );
}

function animateSize(object, manager, w, h, smooth) {
    "use strict";
    var curW = parseFloat(object.css("width")),
        curH = parseFloat(object.css("height"));

    manager.add(
        new AnimationObject(curW, w, manager.time, smooth, ANIMATIONOBJECTWIDTH, object)
    );
    manager.add(
        new AnimationObject(curH, h, manager.time, smooth, ANIMATIONOBJECTHEIGHT, object)
    );
}

function animateOpacity(object, manager, opacity) {
    "use strict";
    var curO = parseFloat(object.css("opacity"));

    manager.add(
        new AnimationObject(curO, opacity, manager.time, false, ANIMATIONOBJECTOPACITY, object)
    );
}

function animateRotation(object, manager, angle, smooth) {
    "use strict";
    console.log(object.angle);
    if (object.angle === undefined) {
        object.angle = 0;
    }

    manager.add(
        new AnimationObject(object.angle, angle, manager.time, smooth, ANIMATIONOBJECTROTATION, object)
    );
}

var view;
function doSomething() {
    "use strict";
    view = $("#test");
    var manager;
    view.html("animating");

    var complete = function () {
        view.html("complete"); 
        manager = null;
        setTimeout(doSomething, 100);
    };

    manager = new AnimationManager(Math.random() * 1.0, complete);
    animatePosition(view, manager, Math.random() * 400, Math.random() * 500, true);
    animateOpacity(view, manager, Math.random());
    animateSize(view, manager, Math.random() * 500, Math.random() * 500, true);
    animateRotation(view, manager, Math.random() * 360, Math.round(Math.random()));
    manager.startAnimation();
}

当我按下按钮时,底部的doSomething方法会运行。 animateRotation方法检测到object.angle未定义并将其设置为0.在动画期间,调用setRotation并将object.angle设置为它的角度(我也可以将console.log设置得很好)。但是当调用complete函数并且动画再次启动时,对象(doSomething方法中的视图).angle将再次重置为undefined。这是怎么回事?

1 个答案:

答案 0 :(得分:0)

就像现在一样,view = $("#test");每次调用doSomething时都会运行,它会选择相同的DOM节点,但每次都返回一个不同的jQuery对象。

解决此问题的最简单方法是执行以下操作:

view = view || $("#test");

但是,您应该重构代码,使其不依赖于全局变量。

一旦你解决了这个问题,你会发现对象上会存在angle属性,但在动画结束时它仍然是未定义的。那是因为上一次setRotation被调用,angle也是undefined