AngularJS等待直到div背景图片显示

13
我有如下的ng-repeat,它从一个$http.post调用中获取数据并将其存储到$scope.data中。
<div ng-repeat="key in [] | range:data.pages">
    <div class="pageBackground" id="page_{{ (key+1) }}" ng-style="{'background-image':'url(/images/{{data.id}}/{{(key+1)}}.png)'}">
    <!-- some random stuff here -->
</div>

通常情况下,屏幕上会先加载 .pageBackground 类,而背景图片却没有加载。我希望在背景图片实际加载之前什么也不会显示出来,但是我一直无法解决这个问题。

有人有什么建议吗?


你能创建一个 plnkr 来重现这个问题吗?在我看来,@sp00m 的回答应该是有效的。 - Joe Enzminger
8个回答

5

我不确定您的问题是否有真正的解决方案。一种解决方法可能是使用Image对象,就像这个答案中所解释的那样。例如,可以将其作为指令使用:

angular.module("yourModule").directive("showOnceBackgroundLoaded", [function () {
  return {
    restrict: "A",
    scope: false,
    link: function (scope, element, attributes) {
      element.addClass("ng-hide");
      var image = new Image();
      image.onload = function () {
        // the image must have been cached by the browser, so it should load quickly
        scope.$apply(function () {
          element.css({ backgroundImage: 'url("' + attributes.showOnceBackgroundLoaded + '")' });
          element.removeClass("ng-hide");
        });
      };
      image.src = attributes.showOnceBackgroundLoaded;
    }
  };
}]);

使用:

<div ng-repeat="key in [] | range:data.pages">
    <div class="pageBackground" id="page_{{ (key+1) }}" show-once-background-loaded="/images/{{data.id}}/{{(key+1)}}.png">
    <!-- some random stuff here -->
</div>

谢谢您的帮助,但这似乎不起作用。一旦div重新出现,背景图像仍然延迟出现。 - bryan

1

请查看以下解决方案:

如何判断CSS背景图片何时加载完成?是否有事件被触发?

你需要创建一个不可见的伙伴元素来加载相同的图片。仅当该图片已经加载完成(onload事件)时,才显示另一个元素。例如:

<div ng-repeat="key in [] | range:data.pages" ng-init="_imageLoaded={}">
    <div ng-show="_imageLoaded[$index]" class="pageBackground" id="page_{{ (key+1) }}" ng-style="{'background-image':'url(/images/{{data.id}}/{{(key+1)}}.png)'}">
    <img ng-show="false" src="/images/{{data.id}}/{{(key+1)}}.png" onload="_imageLoaded[$index] = true;" />
    <!-- some random stuff here -->
</div>

嘿,Patrick,谢谢你的回复。我不确定_imageLoaded={}是从哪里来的。你能给我更多的上下文吗?那个问题对我帮助不大:\ - bryan
嘿,我使用imageLoaded对象来记住每个条目对应的图像是否已加载。因此,在第一次使用_imageLoaded.0时,它将是未定义的 - 但是当加载$index = 0的图像时,它将把该条目设置为true - 这发生在onload函数中。 另一方面,您的div有一个ng-show“监听”这个变量。因此,当它从未定义变为真时,div将弹出。也就是说,当图像加载完成时,这就是您所要求的。_imageLoaded只是实现它的一种方式。 - Patrick Kelleter

0
如果你总是使用相同的class="pageBackground",那么你的背景图片就会一直保持不变。你可以将它加载到隐藏的图像中,这样浏览器就会缓存它:
<img src="url" style="display:none;"/>

或在页面加载时使用JavaScript预加载:

var img = new Image();
img.src = 'some url';

我相信,该帖子是由用户交互触发的,这肯定是在页面加载后发生的,因此图像已经存在于浏览器中,当您应用class="pageBackground"时,它将立即出现。

希望这可以帮到你!


这个类始终保持不变,但是如果你看我的代码,background-image 属性会随着 ng-style 的变化而改变。 - bryan
@bryan 抱歉,我忘了那个,是我的错! - Roman Hutnyk

0

你可以延迟启动函数,直到图像加载完成。

  var img = new Image();
  img.onload = function(){
    loadData();
  };
  img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';

然后在HTML中放置一个ng-if="imageLoaded",并在loadData函数中将其设置为true。

页面/图片的数量从未定义,而且图片始终来自不同的来源。这种方法对于我的示例似乎有点繁琐,但感谢您的建议。 - bryan

0
您可以使用 ngSrc 指令代替 div 元素。此外,您可以尝试使用像 ng-lazy-img 这样的微型延迟加载图像库。
我希望这能帮到您!

0
这是一个使用Image对象的完全功能示例。

function AppCtrl($scope) {
  $scope.images = [{
    src: 'https://farm4.staticflickr.com/3261/2801924702_ffbdeda927_d.jpg'
  }, {
    src: 'https://farm9.staticflickr.com/8455/8048926748_1bc624e5c9_d.jpg'
  }];
  angular.forEach($scope.images, function(image) {
    var img = new Image();
    img.onload = function() {
      $scope.$apply(function() {
        image.loadedSrc = image.src;
      });
    };
    img.src = image.src;
  });
}
.hasSrc {
  color: purple;
  padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
  <div ng-controller="AppCtrl">
    <div ng-repeat="image in images" ng-class="{ hasSrc: !!image.loadedSrc }" style="background-image: url({{image.loadedSrc}})">
      <h2>THIS IS SOME TEXT BEING USED</h2>
      <p>
        This text is being used for illustration purposes only.
      </p>
    </div>
  </div>
</div>

将其适应于您的目的应该很容易。


0

0

这里有一个指令,将您的图像嵌入为背景,并等待图像加载后再显示自己。您可以在“mysrc”参数中包含所需的变量以生成不同的图像(例如在ng-repeat内部)。

angular.module('foo', [])
  .directive('myPageBackground', function() {
    return {
      scope: {
        key: '=', // used for ID of the element; if you set the ID externally to the directive you could omit this
        mysrc: '=' // used for the URL of the desired background image
      },
      template: '<div ng-show="showMe" class="pageBackground" id="page_{{key}}" ng-style="{\'background-image\':\'url({{mysrc}})\'}"></div>',
      link: function(scope) {
        var img = new Image();
        img.onload = function() {
          scope.showMe = true;
          scope.$apply();
        };
        img.src = scope.mysrc;
      }
    }
  });
.pageBackground {
  width: 200px; height: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="foo">
  <!-- Done with hardcoded values here, just for demo: -->
  <div my-page-background key="'1'" mysrc="'http://placehold.it/200x200'"></div>
  <div my-page-background key="'2'" mysrc="'http://placehold.it/150x150'"></div>
  <div my-page-background key="'3'" mysrc="'http://placehold.it/100x100'"></div>
</div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接