Javascript 角度2-预加载背景图像?

Javascript 角度2-预加载背景图像?,javascript,angular,Javascript,Angular,我有一个有角度的项目,我有一个大的背景图片填充页面,还有一个简单的边栏,上面有链接,当点击时,会用另一个图片(来自cdn)更改背景的url。由于这些图像相当大,加载它们需要一两秒钟,这是显而易见的,我想添加一个预加载程序,但我不确定如何在angular 2中完成 在我的html中,我有以下内容: <section class="fullsizebg image-bg" [ngStyle]="{'background-image': 'url(' + urlImage + ')'}">

我有一个有角度的项目,我有一个大的背景图片填充页面,还有一个简单的边栏,上面有链接,当点击时,会用另一个图片(来自cdn)更改背景的url。由于这些图像相当大,加载它们需要一两秒钟,这是显而易见的,我想添加一个预加载程序,但我不确定如何在angular 2中完成

在我的html中,我有以下内容:

<section class="fullsizebg image-bg" [ngStyle]="{'background-image': 'url(' + urlImage + ')'}"></section>

因此,url实际上是即时更改的,但图像加载需要一些时间。我想添加一个加载gif或类似的东西,以保持用户对图像的平滑更改,而不是像现在这样神经质。

一种方法是使用
Blob
获取图像并将其存储在
img
组件中,这样您就可以着手加载过程,并可以添加加载gif:

@组件({
选择器:'loading-image',
模板:“”
})
导出类示例加载图像{
公共src:string=”http://example.com/yourInitialImage.png";
构造函数(私有http:http){}
generateImage(数据:任意):无效{
这个.src=http://www.downgraf.com/wp-content/uploads/2014/09/01-progress.gif“;//只是在google上找到的一个随机加载的gif。
this.http.get('http://example.com/mycdn/“+this.data.url+”.jpg')
.订阅(响应=>{
让urlCreator=window.URL;
this.src=urlCreator.createObjectURL(response.blob());
});
}
}

注意:您应该键入数据参数,键入是确保代码一致性的好方法,
any
只能用作笑话,就像
Java
中的
Object
使用Image Object()


此解决方案利用angular和浏览器已经提供的功能。图像加载由浏览器完成,无需自己处理任何数据或DOM

我已经在Chrome53上测试过了,它工作得非常完美

这是您的元素,正在更改其背景:

<div class="yourBackgroundClass" [style.background-image]="'url(' + imgUrl + ')'"></div>
通过设置
imgPreloadUrl
img
src
通过angular更新,浏览器将图像加载到不可见的
img
标记中。完成后,
onload
启动,我们设置
imgUrl=imgPreloadUrl
。Angular现在更新实际背景的
样式。背景图像
,背景图像立即切换,因为它已加载到隐藏图像中

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>
测试

您几乎不需要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}来自“@angular/core”;
@指令({选择器:'[AppPrelodImage]'})
导出类预加载映像指令{
@输入(“AppPrelodImage”)图像URL:字符串;
构造函数(私有templateRef:templateRef,
私有viewContainer:ViewContainerRef){
}
私有showView(){
this.viewContainer.createEmbeddedView(this.templateRef);
}
恩戈尼尼特(){
var self=这个;
self.viewContainer.clear();
var tmpImg=新图像();
tmpImg.src=self.imageUrl;
tmpImg.onload=函数(){
self.showView();
}
tmpImg.onerror=函数(){
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>


(注意嵌套在双引号中的单引号-这是因为我们传递的是字符串文字。)

我将尝试这样做,但它会破坏我的css以使背景大小覆盖,我不确定如何在角度上做到这一点,我一直使用jquery。你应该寻找css以使img成为固定背景,因为实现您想要的唯一方法就是这样做,使用blob。好的,这比背景问题更重要,我将看看我如何排序,并尝试您的方法。我将得到以下结果:platform browser.umd.js:1900异常:“blob()”方法未在响应超类上实现看起来您没有使用angular最终版本(2.0.X)你能解释一下如何在问题的上下文中使用它吗?@user3836415有人建议我们可以先使用解析器加载图像,这样我们就可以避免延迟加载图像,如果它是登录页的背景图像的话。非常优雅。我将在一个系列中对图像进行预抓取。为照片刷卡工具在索引更改时下拉3个前置索引和3个后置索引。这将使图像下载两次。
<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>
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>