簡體   English   中英

使用Angular.js預加載圖像的最佳方法

[英]Best way to preload images with Angular.js

Angular的ng-src會保留先前的模型,直到它在內部預加載圖像為止。 我在每個頁面上的橫幅使用不同的圖像,當我切換路線時,我更改主視圖,保留標題視圖,只是在擁有它時更改bannerUrl模型。

這導致在加載新的橫幅圖像時看到先前的橫幅圖像。

令我驚訝的是,目前還沒有指令,但是我想在嘗試構建指令之前先進行討論。

我想做的是在自定義屬性上設置橫幅廣告模型。 喜歡:

<img preload-src="{{bannerUrl}}" ng-src="{{preloadedUrl}}">

然后$ scope.watch更改bannerUrl,並在更改后立即用loader spinner替換ng-src,然后創建臨時img dom元素,從preload-src預加載圖像,然后將其關聯到preloadUrl。

例如,還需要考慮如何為畫廊處理多個圖像。

有人對此有意見嗎? 也許有人可以指出我現有的代碼?

我已經在github上看到了使用background-image的現有代碼-但這對我不起作用,因為我的應用程序具有響應能力,因此我需要動態的高度/寬度,而我無法使用background-image來實現。

謝謝

在指令上具有2個url似乎有點復雜。 我認為更好的是編寫一個像這樣的指令:

<img ng-src="{{bannerUrl}}" spinner-on-load />

並且該指令可以監視ng-src並(例如)使用微調框設置可視性:false,直到圖像加載完畢。 所以像這樣:

scope: {
  ngSrc: '='
},
link: function(scope, element) {
  element.on('load', function() {
    // Set visibility: true + remove spinner overlay
  });
  scope.$watch('ngSrc', function() {
    // Set visibility: false + inject temporary spinner overlay
  });
}

這樣,元素的行為就非常類似於具有ng-src屬性的標准img,只是附加了一些額外的行為。

http://jsfiddle.net/2CsfZ/47/

如果有人感興趣,這是我的最終解決方案:我使用twitter bootstrap。 因此,向所有圖像添加了“淡入淡出”類,並且僅在加載圖像時使用指令切換“進入”類以淡入和淡出

angular.module('myApp').directive('imgPreload', ['$rootScope', function($rootScope) {
    return {
      restrict: 'A',
      scope: {
        ngSrc: '@'
      },
      link: function(scope, element, attrs) {
        element.on('load', function() {
          element.addClass('in');
        }).on('error', function() {
          //
        });

        scope.$watch('ngSrc', function(newVal) {
          element.removeClass('in');
        });
      }
    };
}]);

<img img-preload class="fade" ng-src="{{imgSrc}}">

工作示例: http : //ishq.org

如果需要,可以將圖像失敗和圖像加載器作為指令的屬性傳遞。

myApp.directive("mySrc", function() {
    return {
      link: function(scope, element, attrs) {
        var img, loadImage;
        var IMAGE_LOAD="123.jpg";
        var IMAGE_FAIL="123.jpg";
        img = null;

        loadImage = function() {

          element[0].src = IMAGE_LOAD;

          img  = new Image();
          img.src = attrs.mySrc;

          img.onload = function() {
            element[0].src = attrs.mySrc;
          };
          img.onerror=function ()
          {
              element[0].src = IMAGE_FAIL;
          }
        };

        loadImage();


      }
    };
  });

我認為這可能是最優雅的解決方案,因為該指令實際上會創建微調器並自動將其刪除:

app.directive('spinnerLoad', [function spinnerLoad() {
    return {
        restrict: 'A',
        link: function spinnerLoadLink(scope, elem, attrs) {
            scope.$watch('ngSrc', function watchNgSrc() {
                elem.hide();
                elem.after('<i class="fa fa-spinner fa-lg fa-spin"></i>');  // add spinner
            });
            elem.on('load', function onLoad() {
                elem.show();
                elem.next('i.fa-spinner').remove(); // remove spinner
            });
        }
    };
}]);

這是html:

<img ng-src='{{imgUrl}}' spinner-load />

注意:您需要使用超贊的字體才能使它按此處所述工作

只是分享^^

 //css
.media-box{
                position: relative;
                width:220px;
                height: 220px;
                overflow: hidden;
            }
            .media-box div{
                position: absolute;
                left: 0;
                top: 0;
            }
            .spinner{
                position: absolute;
                left: 0;
                top: 0;
                background: #CCC url(./spinner.gif) no-repeat center center;
                display: block;
                width:220px;
                height: 220px;
            }
            .feed img.spinner-show{
                visibility: visible;
            }
            .feed img.spinner-hide{
                visibility: hidden;
            }

//html
<div class="media-box">
  <div>
    <img data-ng-src="{{item.media}}" alt="" title="" data-spinner-on-load>
  </div>
</div>

//js
.directive('spinnerOnLoad', function() {
            return {
                restrict: 'A',
                link: function(scope,element){
                    element.on('load', function() {
                        element.removeClass('spinner-hide');
                        element.addClass('spinner-show');
                        element.parent().find('span').remove();
                    });
                    scope.$watch('ngSrc', function() {
                        element.addClass('spinner-hide');
                        element.parent().append('<span class="spinner"></span>');
                    });      
                }
            }
        });

而不是使用

element.on('load', function() {});

使用imagesLoaded插件。 它將大大加快您的圖像速度。

所以最終的代碼將是:

link: function(scope, element) {
  imagesLoaded(element, function() {

  });
  scope.$watch('ngSrc', function() {

  });
}

我有這個指令,它在img-src更改時顯示一個微調器:

<img-with-loading
      img-src="{{src}}"
      spinner-class="{{spinnerClass}}"
/>

此處的代碼: http : //jsfiddle.net/ffabreti/yw74upyr/

可以使用image-preloader工廠在路線更改時預加載圖像,並解決:

// call REST
                    return getContent.get().$promise.then(function(response) {

                                //return response;

                                // preload images from response
                                var imageLocations = [
                                  // put image(s) from response to array
                                  response.PostImage.big[0],
                                ];

                                // check do we have (all) image(s) in array
                                console.log(imageLocations);

                                // return when all images are preloaded
                                return preloader.preloadImages( imageLocations )
                                .then(function() {

                                    //if it was success 
                                    return response;
                                },
                                function() {

                                        //if it failed 
                                    return response;
                                });

                            });

完整的教程在這里: https : //www.coditty.com/code/angular-preload-images-on-route-change-by-using-resolve

我發現一個簡單的解決方案是在分配新值之前將url更改為“ //:0”

$scope.bannerUrl = 'initial value'; 

// When we want to change it
$scope.bannerUrl = '//:0';  // remove the previous img so it's not visible while the new one loads
$scope.bannerUrl = scope.preloadedUrl

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM