AngularJS:创建一个能够使用$ scope的自定义Object

时间:2014-07-04 14:07:52

标签: javascript angularjs scope

我正在将我的Javascript应用程序从jQuery转换为AngularJS。 我使用了很多Object来修改DOM并为我的元素设置动画。我想创建一个工厂,但我无法访问范围,这不是为什么它们被制造出来的。

指令似乎是一个很好的解决方案,但我不想在我的DOM中声明一个新元素或属性,我希望能够将它用作我控制器中的对象,我想要该对象访问当前控制器范围。

例如:

myModule.controller("myController", ['$scope', 'Animation',
    function($scope, Animation) {
       Animation.doSomeStuff();
    }
]);

是否有任何解决方案或好方法可以做到这一点?

编辑: 我想要转换为Angular方式的jQuery对象的超完整版本:

function Loader() {
var that = this;

this.STATES = new Array("sleep", "animate", "complete");

this.state;
this.animationDuration;
this.animation;
this.currentDiv;
this._completeTimer;
this._contenderResized = new Array();

//Events
this.onComplete = function(){};
this.onStop = function(){};
this.onStart = function(){};

this.init = function(animationName) {

    this.state = "sleep";
    this.animationDuration = 300;

    this.animation = animationName;

    switch(this.animation) {
        case "circle":
            this._initCircle();
            break;
        case "free":
            this._initSquare();
            break;
        case "square":
            this._initSquare();
            break;
    }

};

this.reset = function() {
    this.state = "sleep";
    this.currentDiv.find(".vote").removeClass("activated");

    that.currentDiv.find(".loader").hide();

    switch(this.animation) {
        case "circle":
            this._resetCircle();
            break;
        case "free":
            this._resetSquare();
            break;
        case "square":
            this._resetSquare();
            break;
    }



    this.onComplete = function() {};
    this.currentDiv = "";
};

this._removeAnimationClass = function() {
    this.currentDiv.find(".vote").removeClass("activated");

    var loaderCursor = this.currentDiv.find(".loader-cursor");

    if(loaderCursor.hasClass("loader-cursor-right"))
        loaderCursor.removeClass("loader-animate-right");

    if(loaderCursor.hasClass("loader-cursor-left"))
        loaderCursor.removeClass("loader-animate-left");

    loaderCursor.removeClass("loader-animate");
    loaderCursor.removeClass("loader-complete");
};

this.start = function(contenderDiv) {
    this.currentDiv = contenderDiv;
    this._animate(contenderDiv);
    this._completeTimer = setTimeout(this._complete, this.animationDuration);
};

this.stop = function() {
    if(this.state !== "animate" || !this.currentDiv) return;
    clearTimeout(this._completeTimer);
    switch(this.animation) {
        case "circle" :
            this._stopCircle();
            break;
        case "free":
            this._stopSquare();
            break;
        case "square":
            this._stopSquare();
            break;
    }


    setTimeout(function() {
        //that.currentDiv.find(".loader").hide();
    }, 20);
};

this._animate = function(contenderDiv) {
    this.state = "animate";
    switch (this.animation) {
        case "circle" :
            this._animateCircle(contenderDiv);
            break;
        case "free":
            this._animateSquare(contenderDiv);
            break;
        case "square":
            this._animateSquare(contenderDiv);
            break;
    }
};

this._complete = function() {
    that.state = "complete";
    switch (that.animation) {
        case "circle" :
            that._completeCircle();
            break;
        case "free":
            var loaderCursor = that.currentDiv.find(".loader-cursor");
            loaderCursor.addClass("loader-complete");
            break;
        case "square":
            var loaderCursor = that.currentDiv.find(".loader-cursor");
            loaderCursor.addClass("loader-complete");
            break;
    }

    setTimeout(function() {
        that.onComplete();
        that.reset();
    }, 300);
};

this._resizeLoaderToContainImage = function(contenderDiv){

    if(jQuery.inArray(contenderDiv.find(".vote").attr("rel"),this._contenderResized) !== -1)
        return;

    var img = contenderDiv.find(".contenderImg");

    var imageSrc = jQuery(img).css('backgroundImage')
                   .replace(/url\((['"])?(.*?)\1\)/gi, '$2')
                    .split(',')[0];    
    var image = new Image();
    image.src = imageSrc;
    var bgwidth = image.width,
    bgheight = image.height,    
    bgContainWidth = jQuery(img).width();

    var bgContainHeight = (bgheight*bgContainWidth)/bgwidth;


    var decimal = bgContainHeight.toString().split('.');

    if(decimal[0]>=5)
    {
       bgContainHeight = Math.ceil(bgContainHeight);
    }
    else
    {
       bgContainHeight = Math.floor(bgContainHeight);
    }

    var hRatio = bgheight / parseInt(contenderDiv.css("height"));

    var testWidth = bgwidth / hRatio;

    var decimal = bgContainHeight.toString().split('.');

    if(decimal[0]>=5)
    {
       testWidth = Math.ceil(testWidth);
    }
    else
    {
       testWidth = Math.floor(testWidth);
    }

    console.log("test "+testWidth);

    var loader = contenderDiv.find(".loader");

    loader.css("height", bgContainHeight);
    loader.css("width", testWidth);

    //Center Horizontal
    var marginTop = bgContainHeight / 2;
    loader.css("margin-top", -marginTop);

    //Center Vertical
    var marginLeft = testWidth / 2;
    loader.css("margin-left", -marginLeft);


    this._contenderResized.push(contenderDiv.find(".vote").attr("rel"));
};

/**********************
 *          SQUARE
 **********************/
this._initSquare = function() {

    /*jQuery('.contender').hover(function(){
        //IN
        jQuery(this).find(".loader").show();
        that._resizeLoaderToContainImage(jQuery(this));
    },
     function(){
        //OUT
        jQuery(this).find(".loader").hide();
    });*/
};

this._animateSquare = function(contenderDiv) {

    contenderDiv.find(".contenderImg").addClass("loader-animate");
    contenderDiv.find(".vkrz").stop(true, true).hide().fadeIn(300);

    if(contenderDiv.find("#contenderA").length === 1) {
        jQuery("#contenderB").find(".contenderImg").addClass("loader-animate-grayscale");
    }
    else {
        jQuery("#contenderA").find(".contenderImg").addClass("loader-animate-grayscale");
    }
};

this._stopSquare = function() {
    if(this.currentDiv.find("#contenderA").length === 1) {
        jQuery("#contenderB").find(".contenderImg").removeClass("loader-animate-grayscale");
    }
    else {
        jQuery("#contenderA").find(".contenderImg").removeClass("loader-animate-grayscale");
    }
    this.currentDiv.find(".vkrz").hide();
    this.currentDiv.find(".contenderImg").removeClass("loader-animate");
    this._removeAnimationClass();
};

this._resetSquare = function() {
    jQuery(".vkrz").hide();
    jQuery(".contenderImg").removeClass("loader-animate loader-animate-grayscale");
    this._removeAnimationClass();
};

/**********************
 *          CIRCLE
 **********************/

this._initCircle = function() {
    jQuery('.contender').hover(function(){
    //IN
    jQuery(this).find(".loader").stop(true, true).addClass("loader-hover");
},
 function(){
    //OUT 
    jQuery(this).find(".loader").stop(true, true).removeClass("loader-hover");
});
};

this._animateCircle = function(contenderDiv) {
    contenderDiv.find(".loader").stop(true, true).addClass("loader-animate");
};

this._stopCircle = function() {
    this.currentDiv.find(".vote").removeClass("activated");
    this.currentDiv.find('.loader').removeClass("loader-animate");

};

this._resetCircle = function() {
    this.currentDiv.find(".vote").removeClass("activated");
    jQuery(".loader").removeClass("loader-animate loader-complete").show();
};

this._completeCircle = function() {
    this.currentDiv.find(".loader").addClass('loader-complete');
};
}

2 个答案:

答案 0 :(得分:1)

您无法将指令注入控制器。因此,您可以创建指令并将其添加到HTML或创建服务,将其注入控制器并将$ scope传递给它。

将$ scope传递给服务通常是一种不好的做法,所以我可能会使用指令。

答案 1 :(得分:1)

我认为factory在这里是合适的。它似乎非常适合这项工作:

myModule.factory('Animator', function() {
    // return new Animator instance
    // or if you want a singleton just return it without 'new'
    return new Loader();
});

然后,您的controller可以像这样使用它:

myModule.controller("myController", function($scope, Animator) {
    // init circle animation
    Animator.init('circle');

    $scope.actionOne = function() {
        Animator.start(...);
    };

    $scope.actionTwo = function() {
        Animator.stop();
        Animator.reset();
    };
    ...
});

因此,在这种情况下,您没有将$scope传递给servicefactory实例。相反,您将此类实例注入controller,以便您可以将其与$scope变量一起使用。它也可以根据需要注入尽可能多的控制器,因此它具有高度可重用性。