【问题标题】:Angular2: Show placeholder image if img src is not validAngular2:如果 img src 无效,则显示占位符图像
【发布时间】:2016-07-01 18:53:11
【问题描述】:

目标:加载具有动态源的图像。如果没有找到图像,则加载一个占位符图像。

这应该证明我正在尝试做什么,但我不知道如何根据第一个img src 是否有效来有条件地设置validImage

<img *ngif="validImage" class="thumbnail-image" src="./app/assets/images/{{image.ID}}.jpg" alt="...">
<img *ngif="!validImage" class="thumbnail-image" src="./app/assets/images/placeholder.jpg" alt="...">

如果src="./app/assets/images/{{image.ID}}.jpg" 返回图像,validImage 应该是 true。否则它将返回false,并且只会显示第二个img 标签。

有一些明显的变通方法,例如存储所有有效图像源的列表,但我认为有更好的方法来实现这一点。

任何关于在 Angular2 中实现此功能的最佳方法的建议将不胜感激。

【问题讨论】:

    标签: javascript angular


    【解决方案1】:

    处理损坏的图像链接的最佳方法是为&lt;img&gt; 标签使用onError 事件:

    <img  class="thumbnail-image" src="./app/assets/images/{{image.ID}}.jpg"
          onerror="this.src='./app/assets/images/placeholder.jpg';"  alt="..." />
    

    【讨论】:

    • 需要注意的一点,确保您的占位符图像始终在该位置,否则我认为您可能会陷入无限循环:)
    • 为什么它创建进入一个循环?
    • 有没有办法抑制记录的 404 错误?
    • 太棒了!!但是不明白为什么要使用this.src?没有这个它也应该工作,但不能工作
    • icanuse, caniuse.com/mdn-html_elements_img_onerror 将 onerror 列为“此功能已弃用/过时,不应使用。”以及 IE11 不支持此功能(对于那些必须提供商业支持的人)
    【解决方案2】:
    <img class="thumbnail-image" src="getImage()" alt="...">
    
    getImage():string{  //I don't know how would you handle your situation here. But you can think of it.
    
      if (this.validImage) // I don't know how would you manage validImage here.
      {
         return this.validImagePath;
      }
    
       return this.placeholderImagePath;
    }
    

    【讨论】:

      【解决方案3】:
      src="validImage ? validImageUrl : placeHolderImgUrl"
      

      【讨论】:

      • 如果结果作为错误请求返回则不起作用。必须使用@JanR 的答案。
      【解决方案4】:

      我遇到了类似的需求。如果 img url 为空或返回错误(404 等),我想默认为 1X1 透明像素。

      import { Directive, Input } from '@angular/core';
      
      @Directive({
          selector: 'img[src]',
          host: {
              '[src]': 'checkPath(src)',
              '(error)': 'onError()'
          }
      })
      export class DefaultImage { 
          @Input() src: string;
          public defaultImg: string = '{YOUR_DEFAULT_IMG}';
          public onError() {
              this.src = this.defaultImg;
          }
          public checkPath(src) {
              return src ? src : this.defaultImg;
          }
      }
      

      标记

      <img [src]="{DESIRED_IMAGE_SOURCE}" />
      

      【讨论】:

      • 优秀的解决方案,因为 src 可以为空,在这种情况下不会抛出 404 错误。
      • 您能否展示一个使用您的解决方案的模板示例?
      • 我认为onError() 在这种情况下实际上不会做任何事情?它只是返回一个字符串...
      • onError部分需要改为this.src = this.defaultImg;
      【解决方案5】:
      <img [src]="pic" (error)="setDefaultPic()">
      

      在你的组件类中的某个地方:

      setDefaultPic() {
        this.pic = "assets/images/my-image.png";
      }
      

      【讨论】:

      • 比公认的答案更好。它允许您在出错时做更多的事情(删除 img 标签并显示文本可能......),而不仅仅是更改 img src。
      【解决方案6】:

      如果图像仍未加载或加载时出现错误,我创建了一个使用占位符图像的自定义组件:

      img.component.ts:

      import { Component, Input, OnChanges } from '@angular/core';
      
      @Component({
          selector: 'my-img',
          templateUrl: 'img.component.html',
      })
      export class ImgComponent implements OnChanges {
          @Input() 
          public src: string;
          @Input() 
          public default: string;
          @Input() 
          public alt: string;
          public cached = false;
          public loaded = false;
          public error = false;
      
          private lastSrc: string;
      
          constructor() { }
      
          public ngOnChanges() {
              if (this.src !== this.lastSrc) {
                  this.lastSrc = this.src;
                  this.loaded = false;
                  this.error = false;
                  this.cached = this.isCached(this.src);
              }
      
              if (!this.src) {
                  this.error = true;
              }
          }
      
          public onLoad() {
              this.loaded = true;
          }
      
          public onError() {
              this.error = true;
          }
      
          private isCached(url: string): boolean {
              if (!url) {
                  return false;
              }
      
              let image = new Image();
              image.src = url;
              let complete = image.complete;
      
              // console.log('isCached', complete, url);
      
              return complete;
          }
      }
      

      img.component.html:

      <ng-container *ngIf="!cached">
          <img 
              *ngIf="!error" 
              [hidden]="!loaded"
              [src]="src" 
              [alt]="alt" 
              (load)="onLoad()" 
              (error)="onError()"
          >
          <img 
              *ngIf="default && (error || !loaded)" 
              [src]="default" 
              [alt]="alt"
          >
      </ng-container>
      
      <ng-container *ngIf="cached">
          <img 
              *ngIf="!error" 
              [src]="src" 
              [alt]="alt" 
              (error)="onError()"
          >
          <img 
              *ngIf="default && error" 
              [src]="default" 
              [alt]="alt"
          >
      </ng-container>
      

      然后你可以像这样使用它:

      <my-img [src]="src" [alt]="alt" [default]="DEFAULT_IMAGE"></my-img>
      

      PS:我预先验证图像是否被缓存以避免图像在占位符和图像之间闪烁(通常是在重新渲染内部包含图像的组件时)(如果它被缓存,我显示甚至在加载标志设置为 true 之前的图像)。您可以在isCached函数中取消注释日志以查看您的图像是否被缓存。

      【讨论】:

      • 我是否正确,在您的解决方案中,您分别缓存每个图像组件,从而在页面上出现的每个相同图像上花费额外的内存(例如:表格中多个单元格显示相同的图像,其他单元格不同一)?我几乎可以肯定,在这种情况下,浏览器默认的图像缓存会更有效。
      • @ArseniiFomin 缓存不是独立的。每个图像只有一个缓存(除非您包含一些参数来绕过它,但是当您使用 img src 时也会发生这种情况)。如果同一图像的缓存不同,则在调用isCached() 时,它总是会返回false。您可以测试在img 标记中加载图像,并在调用new Image() 传递相同的src 并看到isCached() 同步返回true(因为它使用相同的缓存)。您还可以在浏览器检查器中进行检查以查看网络调用。
      • @ArseniiFomin 只是为了补充我之前所说的,javascript原生Image使用浏览器默认缓存:https://stackoverflow.com/a/10240297/4850646
      • 所以所有的缓存都是在 Image 类实现内部完成的?
      • javascript Image 使用浏览器缓存。从MDN web docsImage() 构造函数创建一个新的HTMLImageElement 实例。它在功能上等同于document.createElement('img')
      【解决方案7】:

      我刚刚这样做了:

      在我的 HTML 文件中写了这个

      <div 
         (click)="getInfo(results[movie].id)"
         *ngFor="let movie of (results | key:'10')" 
          class="card" style="margin-top:7%;">
       <img [src]="getImage(results[movie])" alt="" class="card-img-top pointer"></div>
      

      我调用了我的 component.ts 中的一个函数,并将我的 url 所在的对象作为参数传递

      getImage(result){
      if(result.poster_path){
        return this.imageURL+(result.poster_path);
      }else return "./assets/noFound.jpg"
      

      继承我的功能,首先我验证对象图像 url 是否不同于 null 如果为真,然后我返回图像 url,否则我返回我的应用程序资产中的默认“noFound”图像。
      希望对您有所帮助!

      【讨论】:

        【解决方案8】:

        如果您想处理班级中的错误,以下方法也适用:

        在您的模板中:

        <img [src]='varWithPath' (error) ="onImgError($event)">
        

        在你的课堂上:

        onImgError(event) { 
            event.target.src = 'assets/path_to_your_placeholder_image.jpg';
        }
        

        【讨论】:

        • 我更喜欢这个选择的答案,我觉得它更干净。谢谢!
        猜你喜欢
        • 1970-01-01
        • 2020-12-05
        • 1970-01-01
        • 1970-01-01
        • 2021-08-13
        • 2023-03-28
        • 2015-10-08
        • 2018-09-02
        • 1970-01-01
        相关资源
        最近更新 更多