2014-01-07 56 views
25

Angular的ng-src保留之前的模型,直到它在內部預加載圖像。我在每個頁面的橫幅上使用了不同的圖像,當我切換路線時,我改變了主視圖,將標題視圖保持原樣,只是在擁有它時更改bannerUrl模型。使用Angular.js預加載圖像的最佳方式

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

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

我想做什麼我認爲是自定義屬性上的橫幅模型。像:

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

然後$ scope.watch爲bannerUrl變化,只要它的變化,替換裝載機微調NG-SRC第一,然後創建temproary IMG DOM元素,從預壓SRC,然後預載圖片分配給preloadUrl。

需要思考如何處理畫廊的多個圖像,例如。

有沒有人有任何輸入?或者也許有人可以指向我現有的代碼?

我看過github上使用background-image的現有代碼 - 但這不適合我,因爲我需要動態高度/寬度,因爲我的應用程序是響應式的,而且我無法使用background-image。

謝謝

+0

通常的解決方法是使用CSS將圖像設置爲'visibility:hidden',直到最終圖像被加載,當您將其更改爲'visibility:visible'時,因此您只能看到最終圖像。 – jfriend00

+0

@ jfriend00將所有圖像設置爲'visibility:hidden',然後使用javascript查看數組中所有圖像何時加載,並將所有圖像設置爲'visibility:visible'然後? – Yuri

回答

46

對指令有2個網址似乎觸摸過於複雜。我認爲是更好的是寫這就像一個指令:將圖片加載錯誤了微調:

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

而且該指令可以觀看ng-src和(例如)設置可見。因此,像:

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/

+0

總體感覺,謝謝。今天下午會嘗試。 – Yuri

+0

謝謝先生。我已經進一步擴展了你的想法,並且完美。 – Yuri

+0

that works - > http://jsfiddle.net/2CsfZ/47/ –

22

如果有人有興趣,這是我最終的解決方案:我使用Twitter的引導。因此,添加的類「變臉」的所有圖像的,只是切換類「中的」使用指令淡入和淡出的時候圖像加載

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

+1

欣賞鏈接到一個現實世界的示例,但是您能否將這些好東西分爲Plunker或其他在線沙盒測試環境?謝謝 – ScottN

+0

正是我在找的東西。謝謝 – Vinnyq12

1

只是爲了分享^^

//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>'); 
        });  
       } 
      } 
     }); 
1

而不是使用

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

使用imagesLoaded的 插入。它會加快你的圖像。

所以最終的代碼如下:

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

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

    }); 
} 
3

如果你願意,你可以通過圖像失敗和圖像加載器作爲指令屬性....

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(); 


     } 
    }; 
    }); 
-1

一個簡單的解決方案,我我們發現在分配它的新值之前將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 
0

我有此指令whic H顯示一個微調時,IMG-SRC變化:

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

代碼在這裏:http://jsfiddle.net/ffabreti/yw74upyr/

2

我想,這也許是最優雅的解決方案,因爲該指令實際上創建了微調,並自動刪除它:

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 /> 

注意:你需要使用字體真棒這個通過使用image-preloader工廠和決心這裏描述

+0

一個愚蠢的問題,但我怎樣才能在一個具有自己的控制器的HTML模板中使用該指令?我在index.html中添加了directive.js文件,但它顯示typerrror(elem.hide&elem.show不是函數)。範圍也是類型($ scope)?謝謝:) – Jamie

+0

這不適合我。 watch函數被調用一次,當src被更新時它不會觸發watch函數。 –

0

圖像可以在路由改變被預載的工作:

// 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

相關問題