良い一日、
私はIonicアプリケーションで作業しており、JSONフィードから動的に画像をロードしています。画像が外部URLからプルされているときに、プレースホルダー画像が表示されるようにしたいのですがその場所、その後、プレースホルダー画像は、読み込まれると「実際の」画像に置き換えられます。
私の現在の状況の例は:
<ion-card *ngFor="let item of items"...
<img [src]="item.picture" />
ありがとうございます。それでは、お元気で。
JSONを変更してloaded
booleanプロパティを持つことができますか?これが簡単な場合は、次のようにします。
_<ion-card *ngFor="let item of items">
<img [src]="item.picture" (load)="item.loaded = true" [hidden]="!item.loaded" />
<img src="../path/to/your/placeholer/image.jpg" [hidden]="item.loaded">
</ion-card>
_
ロードされたプロパティは常にfalse
として初期化されます。画像が読み込まれると、_(load)
_イベントが発生し、画像の読み込まれたプロパティがtrueに変更され、プレースホルダー画像が非表示になり、読み込まれた画像が表示されます。
このJSONを変更できない場合(またはサイズが大きすぎて編集できない場合)、上記のコードを使用できますが、ページで次のようにしてください_.ts
_
_public functionWhoseIsLoadingYourJson(){
// HTTP REQUEST FOR JSON
.subscribe(response => {
response.forEach(element => {
element.loaded = false;
});
this.items = response;
});
}
_
応答を繰り返し、すべてのオブジェクトでロードされたプロパティをfalseに設定します。これが何らかのエラーをスローする場合、* ngIfを使用して_<ion-card>
_をdiv内に置くことができます
_<div *ngIf="this.items != null">
<!-- ion card -->
</div>
_
Firebaseから提供されているため、JSONを更新するには3つのオプションがあります。 1つ目は、データベースを更新するために1回だけ実行する関数です。2つ目は、私が与えたコードです(結果を繰り返し処理し、ブール値をプッシュします)が、Firebaseを使用しているため、異なります。
最初の解決策:
あなたのコードのどこかで、それはどんなページでもかまいません、あなたはそれを一度実行するだけです:
_firebase.database().ref('myDataNode').on('value', snapshot => {
for(let key in snapshot.val()){
firebase.database().ref('myDataNode/' + key + '/loaded').set(false);
}
});
_
myDataNode
のすべての結果をループし、それらのキーを使用してloaded
プロパティをfalse
に設定していることを確認してください。ただし、set
を使用する場合は注意してください。すべてのノードをオーバーライドできるため、この方法を実行する前に、Firebaseノードをエクスポートしてバックアップを作成することを忘れないでください。また、コード内の任意の場所から画像をFirebaseにプッシュする場合は、loaded
プロパティを一緒に設定するように変更することを忘れないでください。
前述のように、2つ目はこの回答で行ったものですが、Firebase呼び出し内で使用し、スナップショットに付属するforEachメソッドを使用します。
_firebase.database().ref('myDataNode').on('value', snapshot => {
snapshot.forEach(element =>{
this.myDataNode.Push({
picture: element.val(), // maybe it needs to be element.val().nameOfYourProperty
loaded: false
})
});
});
_
これにより、画像のURLと読み込まれたプロパティを持つ新しい要素が配列にプッシュされます。 .Push()
メソッドを認識できない場合は、配列として型指定された変数を宣言します。
_public myDataNode: any[];
_
3つ目は、ローカルでの更新、firebaseスナップショットの反復、ローカル変数への結果の保存、新しいプロパティの作成、配列へのプッシュです。
_firebase.database().ref('myDataNode').on('value', snapshot => {
for (let key in snapshot.val()){
snapshot.forEach(item => { // iterate snapshot
let record = item.val(); // save the snapshot item value in a local variable
record.loaded = true; // add the property
this.newArray.Push(record); // Push it to your array that'll be used in ng-for
return true; // return true to foreach
});
}
});
_
お役に立てれば。
ほとんどの回答は、同じビューにloaded checkのロジックを追加することに関するものですが、適切ではないようです。代わりに、それを処理する独自のディレクティブを作成できます。 この驚くべき記事を見て、それがどのように実行できるかを確認できます。
最初のコピーこのGIFsrc/assets
フォルダに名前を付け、preloader.gif
。
次に、このカスタムディレクティブを追加します。コードはほとんど自明です:
// An image directive based on http://blog.teamtreehouse.com/learn-asynchronous-image-loading-javascript
import {Directive, Input, OnInit} from '@angular/core';
// Define the Directive meta data
@Directive({
selector: '[img-preloader]', //E.g <img mg-img-preloader="http://some_remote_image_url"
Host: {
'[attr.src]': 'finalImage' //the attribute of the Host element we want to update. in this case, <img 'src' />
}
})
//Class must implement OnInit for @Input()
export class ImagePreloader implements OnInit {
@Input('img-preloader') targetSource: string;
downloadingImage : any; // In class holder of remote image
finalImage: any; //property bound to our Host attribute.
// Set an input so the directive can set a default image.
@Input() defaultImage : string = 'assets/preloader.gif';
//ngOnInit is needed to access the @inputs() variables. these aren't available on constructor()
ngOnInit() {
//First set the final image to some default image while we prepare our preloader:
this.finalImage = this.defaultImage;
this.downloadingImage = new Image(); // create image object
this.downloadingImage.onload = () => { //Once image is completed, console.log confirmation and switch our Host attribute
console.log('image downloaded');
this.finalImage = this.targetSource; //do the switch ????
}
// Assign the src to that of some_remote_image_url. Since its an Image Object the
// on assignment from this.targetSource download would start immediately in the background
// and trigger the onload()
this.downloadingImage.src = this.targetSource;
}
}
次に、次のように新しいディレクティブをアプリモジュールに追加します。
import { NgModule, ErrorHandler } from '@angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { ImagePreloader } from '../components/img-preload/img-preload';
@NgModule({
declarations: [
MyApp,
ImagePreloader, // <------- Here!
// ...
],
imports: [
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
// ...
],
providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}]
})
export class AppModule {}
これは、新しいカスタムディレクティブを使用する方法です。
<img img-preloader="https://images.unsplash.com/photo-1413781892741-08a142b23dfe" alt="">
これは次のようになります。
次に、画像のコンテナの高さ/幅を設定して、プリローダーgifと最終画像の両方が同じサイズになるようにします。
以下のようにしてみてください。プレースホルダー画像はassets/images
フォルダーに保存できます。
。html
<ion-card *ngFor="let item of items">
<img [src]="item?.picture!= null ? item.picture : myImgUrl" />
</ion-card>
。ts
export class MyPage{
myImgUrl:stirng='./assets/images/myimage.png;
constructor(){}
}
私の知る限り、Ionicを実行する方法はありません。ただし、javascriptとcssを使用して実行できます。
画像をカバーするdivを作成し、プレースホルダー画像をそのdivのbackground-image
に設定します。
<div class="image">
<img src="your_main_image"/>
</div>
.image{
background-image: url('your_placeholder_image');
}
Stackoverflowで簡単に見つけることができるJavaScriptによる方法がいくつかあるので、ここでは再回答しません。 これ は例です