我试图将一个 $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
值添加到高度的一半和宽度的一半会将元素直接放在图像的中心。
当我在未打开开发者工具的情况下在 Google Chrome 中运行应用程序时,在加载图像并调整元素的高度和宽度时不会调用 centerElement 指令监视,但是当我通过单步运行应用程序时Chrome 开发者工具,元素在图像上居中就好了。当我在没有它的情况下运行应用程序后打开开发人员工具时,没有任何错误。
此外,我尝试在 Internet Explorer、Edge 和 Firefox 中运行该应用程序。 Internet Explorer 和 Firefox 都以与 Chrome 相同的方式运行,但是,Edge 是唯一一个按照预期方式将图像居中的浏览器。
我宁愿不使用 $watch,因为它可能有性能问题,但根据我在文档和谷歌上所做的研究,我还没有找到另一种方法来做到这一点,但我非常开放的想法。我试图在等待图像加载然后将元素居中时找到一些东西,但我没有运气。我将在应用程序的其他部分重复此指令,因此不必使用 $watch 会很棒。
我是 angularJS 的新手,所以非常感谢任何帮助。我还不熟悉如何在 stackoverflow 上提问,所以如果您需要更多信息,请告诉我。
谢谢!
编辑: 我为图像创建了另一个指令,它会在加载时调用 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');
});
}
};
});
最佳答案
这是我自己想出来的。我需要将 $timeout();
添加到我的 centerElement
指令中。这会在当前 $digest
完成时强制执行 $scope.$apply();
,以便在 $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%
, margin-top
负值和元素高度的一半以及 margin-left
负值和宽度的一半(即 margin-top: -100px
当元素高度为 200px 和 margin-left: -50px
当元素宽度为 100px 时)顺序使元素在图像上居中。我需要找出元素的宽度和高度,而不是将其硬编码到 CSS 中,这在将来出于维护目的可能会很乏味,因为我必须计算出所有屏幕尺寸的尺寸以进行引导。这就是我使用 $watch
的原因。
我也在使用 Bootstrap ,所以 CSS3 flexbox
是不可能的,因为它会扰乱 Bootstrap 网格的响应能力。
因此,如果有人对如何摆脱 $watch 有任何想法,请告诉我。
关于javascript - AngularJs - $watch 仅在 Chrome 开发者工具打开时有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35532183/