我试图将$ watch附加到指令,该指令监视元素的高度和宽度何时发生变化,以便它可以使用高度和宽度居中于图像顶部。
这是我的app.js代码:
app.directive('centerElement', function ($timeout) {
return function (scope, element, attrs) {
scope.$watch(function () {
return {
'h': element[0].offsetHeight,
'w': element[0].offsetWidth
};
},
function (newValue, oldValue) {
var elementHeight = newValue.h;
var elementWidth = newValue.w;
/*To account for rounding errors and not loop*/
if(elementHeight % 2 === 0)
{
element.css('margin-top', '-' + ((elementHeight) / 2) + 'px');
}
else
{
element.css('margin-top', '-' + ((elementHeight + 1) / 2) + 'px');
}
if(elementWidth % 2 === 0)
{
element.css('margin-left', '-' + ((elementWidth) / 2) + 'px');
}
else
{
element.css('margin-left', '-' + ((elementWidth + 1) / 2) + 'px');
}
}, true);
element.bind('centerElement', function () {
scope.$apply();
});
};
});
这是我的HTML代码:
<div class="row relativePosition">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 noPadding">
<img id="getStartedGiveGiftImage" ng-src="{{homeCtrl.getHomeImageBySectionName('getStartedGiveGift').url}}"/>
</div>
<div id="getStartedGiveGiftCol" class="absolutePosition" center-element>
<div class="col-lg-8 col-md-8 col-sm-8 col-xs-12">
<div class="getStartedGiveGiftText headingTitle">
Swapping, Sharing,
<div class="getStartedGiveGiftText text-right">
and Caring
</div>
</div>
</div>
<div id="getStartedGiveGiftButtons" class="col-lg-4 col-md-4 col-sm-4 col-xs-12 text-right">
<div>
<a id="getStartedGiveGiftButton1" class="btn btn-default text-right redBackgroundGradient" href="{{homeCtrl.getPage('Get Started').route}}">Get Started</a>
</div>
<div>
<a id="getStartedGiveGiftButton2" class="btn btn-default getStartedGiveGiftButton greenBackgroundGradient text-right text-white" href="{{homeCtrl.getPage('Give a Gift').route}}">Give a Gift</a>
</div>
</div>
</div>
</div>
我已将.getStartedGiveGiftCol的css设置为
#getStartedGiveGiftCol {
top: 50%;
left: 50%; }
将margin-top
和margin-left
值添加到高度的一半和宽度的一半会将元素直接放在图像的中心。
当我在未启用开发者工具的情况下在谷歌浏览器中运行该应用程序时,在加载图像并调整元素的高度和宽度时,无法调用centerElement指令监视,但是当我运行应用程序时通过Chrome开发者工具,元素可以很好地在图像上居中。在没有它的情况下运行应用程序后打开开发人员工具时,没有错误 此外,我尝试在Internet Explorer,Edge和Firefox中运行该应用程序。 Internet Explorer和Firefox的行为与Chrome的行为方式相同,但Edge是唯一以图像方式居中的浏览器。
我宁愿不使用$ watch因为它可能会出现性能问题,但是从我在文档和谷歌上所做的研究中我还没有找到另一种方法来做到这一点但我对创意非常开放。我试图找到一些东西等待图像加载然后居中元素,但我没有运气。我将在应用程序的其他部分重复此指令,因此不必使用$ watch会很棒。
我对angularJS很新,所以非常感谢任何帮助。我也很想在stackoverflow上提问,所以如果你需要更多信息,请告诉我。
谢谢!
修改 我为image创建了另一个指令,它会在加载时调用scope。$ digest()。它似乎有所帮助,但是当我多次刷新页面时,有时它仍然无法正常工作。有什么想法吗?
这是我添加的指令:
app.directive('imageOnload', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.bind('load', function() {
scope.$digest();
});
element.bind('error', function(){
alert('image could not be loaded');
});
}
};
});
答案 0 :(得分:0)
我自己想出来了。我需要将$timeout();
添加到我的centerElement
指令中。这会在当前$scope.$apply();
完成时强制$digest
,以便$watch
中所做的更改实际应用于页面。
我的指示如下:
app.directive('centerElement', function ($timeout) {
return function (scope, element, attrs) {
scope.$watch(function () {
$timeout();
return {
'h': element[0].offsetHeight,
'w': element[0].offsetWidth
};
},
function (newValue, oldValue) {
var elementHeight = newValue.h;
var elementWidth = newValue.w;
/*To account for rounding errors and not loop*/
if(elementHeight % 2 === 0)
{
element.css('margin-top', '-' + ((elementHeight) / 2) + 'px');
}
else
{
element.css('margin-top', '-' + ((elementHeight + 1) / 2) + 'px');
}
if(elementWidth % 2 === 0)
{
element.css('margin-left', '-' + ((elementWidth) / 2) + 'px');
}
else
{
element.css('margin-left', '-' + ((elementWidth + 1) / 2) + 'px');
}
}, true);
element.bind('centerElement', function () {
scope.$apply();
});
};
});
如果有人对如何避免使用$watch
有任何想法,请告诉我。我不能仅使用CSS,因为row
为position: relative
且元素为position: absolute
所以我必须使用top: 50%
,left: 50%
,{ {1}}负数和元素高度的一半,margin-top
负数和宽度的一半(当元素高度为200px时为margin-left
,当元素宽度为100px时为margin-top: -100px
)为了使元素在图像上居中。我需要找出元素的宽度和高度,而不是将其硬编码到CSS中,这在将来用于维护时可能会很繁琐,因为我必须弄清楚引导程序的所有屏幕大小的大小。因此,为什么我使用margin-left: -50px
。
我也使用bootstrap,因此CSS3 $watch
是不可能的,因为它会扰乱引导网格响应。
因此,如果有任何想法如何摆脱$ watch,请告诉我。