我正在将我的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');
};
}
答案 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
传递给service
或factory
实例。相反,您将此类实例注入controller
,以便您可以将其与$scope
变量一起使用。它也可以根据需要注入尽可能多的控制器,因此它具有高度可重用性。