[英]Angular 2 - Preload background image?
我有這個角度項目,我有一個填充頁面的大背景圖像和一個帶有鏈接的簡單側邊欄,點擊后,將用另一個圖像(來自cdn)更改背景的URL。 由於這些圖像相當大,它們需要一兩秒才能加載並且它很明顯,我想添加一個預加載器,但我不確定如何在角度2中完成。
在我的HTML中我有這個:
<section class="fullsizebg image-bg" [ngStyle]="{'background-image': 'url(' + urlImage + ')'}"></section>
變量urlImage填充在組件的構造函數中,側邊欄鏈接在單擊時更改它的值,使用一個簡單的函數,如下所示:
generateImage(data: any){
this.urlImage = 'http://example.com/mycdn/'+this.data.url+'.jpg';
}
因此,網址實際上會立即更改,但圖像需要加載一些。 我想添加一個加載gif或類似的東西,以保持圖像變化順利給用戶,而不是像現在一樣跳躍。
一種方法是使用Blob
獲取圖像並將其存儲在img
組件中,這樣您就可以完成加載過程了,並且可以添加加載gif:
@Component({
selector:'loading-image',
template:'<img alt="foo" [src]="src"/>'
})
export class ExampleLoadingImage{
public src:string = "http://example.com/yourInitialImage.png";
constructor(private http:Http){}
generateImage(data: any): void {
this.src = 'http://www.downgraf.com/wp-content/uploads/2014/09/01-progress.gif'; //Just a random loading gif found on google.
this.http.get('http://example.com/mycdn/'+this.data.url+'.jpg')
.subscribe(response => {
let urlCreator = window.URL;
this.src = urlCreator.createObjectURL(response.blob());
});
}
}
注意 :你應該鍵入你的數據參數,鍵入是確保代碼一致性的好方法, any
只應該用作joker,比如Java
Object
。
該解決方案利用了角度和瀏覽器已經提供的角度。 圖像加載由瀏覽器完成,無需自己處理任何數據或DOM。
我已經在Chrome 53上對它進行了測試,它運行良好。
這是你的元素,它的背景改變了:
<div class="yourBackgroundClass" [style.background-image]="'url(' + imgUrl + ')'"></div>
要預取圖像,我們使用未顯示的圖像標記。 最好另外確定它的position: absolute
並將其移出視圖或使其非常小,這樣它就不會干擾您的實際內容。
<img [src]="imgPreloadUrl" (load)="imgUrl = imgPreloadUrl" hidden>
通過設置imgPreloadUrl
, img
的src
按角度更新,瀏覽器將圖像加載到不可見的img
標簽中。 一旦完成, onload
觸發,我們設置imgUrl = imgPreloadUrl
。 Angular現在更新了實際背景的style.background-image
,並且背景圖像立即切換,因為它已經加載到隱藏圖像中。
在imgUrl !== imgPreloadUrl
我們可以顯示一個微調器來指示加載:
<div class="spinner" *ngIf="imgUrl !== imgPreloadUrl"></div>
測試:
<button (click)="imgPreloadUrl = 'https://upload.wikimedia.org/wikipedia/commons/2/24/Willaerts_Adam_The_Embarkation_of_the_Elector_Palantine_Oil_Canvas-huge.jpg'">test</button>
使用圖像對象 ( Plunker演示 ⇗ )
tmpImg: HTMLImageElement; // will be used to load the actual image before showing it
generateImage(data: any){
this.urlImage = 'http://example.com/mycdn/'+ 'loading_GIF_url'; // show loading gif
let loaded = () => { // wait for image to load then replace it with loadingGIF
this.urlImage = 'http://example.com/mycdn/' + this.data.url+'.jpg';
}
// background loading logic
if(this.tmpImg){
this.tmpImg.onload = null; // remove the previous onload event, if registered
}
this.tmpImg = new Image();
this.tmpImg.onload = loaded; // register the onload event
this.tmpImg.src = 'http://example.com/mycdn/'+this.data.url+'.jpg';
}
你需要的東西很少,如http,解析器和消毒劑。 這是一個解釋如何從頭開始實現它的鏈接 。
因此,例如,您有一個請求,然后將返回的blob轉換為安全樣式,以便我們能夠在style指令中使用它
this.http.get('assets/img/bg.jpg', { responseType: 'blob' }).pipe(
map( image => {
const blob: Blob = new Blob([image], { type: 'image/jpeg' });
const imageStyle = `url(${window.URL.createObjectURL(blob)})`;
return this.sanitizer.bypassSecurityTrustStyle(imageStyle);
})
)
我最近將其作為結構指令實現 :
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({ selector: '[appPreloadImage]'})
export class PreloadImageDirective {
@Input("appPreloadImage") imageUrl : string;
constructor( private templateRef : TemplateRef<any>,
private viewContainer : ViewContainerRef) {
}
private showView() {
this.viewContainer.createEmbeddedView(this.templateRef);
}
ngOnInit() {
var self = this;
self.viewContainer.clear();
var tmpImg = new Image();
tmpImg.src = self.imageUrl;
tmpImg.onload = function() {
self.showView();
}
tmpImg.onerror = function() {
self.showView();
}
}
}
你可以像這樣使用它:
<div *appPreloadImage="'/url/of/preloaded/image.jpg'">
<!-- Nothing in here will be displayed until the
request to the URL above has been completed
(even if that request fails) -->
</div>
(注意嵌套在雙引號內的單引號 - 這是因為我們傳遞的是字符串文字。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.