I had a requirement to have an image grid-like image gallery.
I gone through the many tutorials and blogs. All were not suitable for my purpose.
- Some works with square sized images.
- Some works with hard-coded grid tile width.
- Some works on responsive design using fixed with image tile. I could not use this one because I need to use virtual-scroll.
- All work with the known number of items. All number of rows and columns are decided in the beginning.
Let's try with a sample application.
Create a blank App with the name 'ImageGrid'
ionic start ImageGrid
this will create the starting project. We will focus on the home.html, home.ts and home.scss only.
Image grid can be visualized as a 2D matrix with a fixed number of columns and variable numbers of row.
As I came from C/C++ background and know that internally 2D array is a contiguous memory allocation. So I decided to handle the 2D image matrix like a simple array.
Check the basic concept
// Create a type, you can add more fields to this type as per your requirement. interface FileObject { public thumbnail: string; } const _grid_columns_count: number = 3; // Number of columns in image grid //Get a specific item by row and column yourFunction(row: number, col: number) { let i = row * _grid_columns_count + col; } // Here i is index by which you can query an item by row and column.
Full Source code
Home.ts
Home.ts
import { Component } from '@angular/core'; import { NavController } from 'ionic-angular'; interface FileObject { thumbnail: string; } const _grid_columns_count: number = 3; // Number of columns in image grid @Component({ selector: 'page-home', templateUrl: 'home.html' }) export class HomePage { private columns: Array<number>; private rows: Array<number>; private fileObjects: FileObject[]; constructor(public navCtrl: NavController) { // Create column array for number of columns you want this.columns = new Array(_grid_columns_count); // This array will hold the number of rows this.rows = new Array<number>(); // This array will hold all the items in the grid. // Add a item by appending or inserting // Remove a item by delete your item from the array this.fileObjects = new Array<FileObject>(); } // Add item addItem(obj: FileObject) { this.fileObjects.push(obj); // true of if condition indicates that we need a new row. if ((this.rows.length * _grid_columns_count) < this.fileObjects.length) { this.rows.push(this.rows.length); } } // Get an item by row and column getItemThumbnail(row: number, col: number) { let i = row * _grid_columns_count + col; if (i < this.fileObjects.length) { return this.fileObjects[i].thumbnail; } else { return "no found"; } } isValid(row: number, col: number): boolean { let i = row * _grid_columns_count + col; return (i < this.fileObjects.length); } onTapImage(row, col) { let i = row * _grid_columns_count + col; if (i < this.fileObjects.length) { alert(this.fileObjects[i].thumbnail); } } getTileHeight(): string { return "100px;" } /* This is a method just to simulate how we can items change the image path as per your wish */ addImages() { for (let i = 0; i < 8; ++i) { let obj: FileObject = { thumbnail: 'url("../assets/icon/image.jpg")' } this.addItem(obj); } } }
Home.html
<ion-header> <ion-navbar color="dark"> <ion-title> {{fileObjects.length}} files </ion-title> </ion-navbar> </ion-header> <ion-content padding style="background-color:#222"> <ion-list [virtualScroll]="rows" approxItemHeight="{{getTileHeight()}}" no-margin> <ion-row *virtualItem="let row" class="item-row"> <ion-col *ngFor="let column of columns; let col = index"> <div *ngIf="isValid(row, col)" [style.background-image]="getItemThumbnail(row, col)" class="image-background" (tap)="onTapImage(row, col)"> </div> </ion-col> </ion-row> </ion-list> </ion-content> <ion-footer> <ion-toolbar color="dark" style="text-align:center;"> <!-- Button just to trigger the adding items --> <button ion-button round (tap)="addImages()">Add Images</button> </ion-toolbar> </ion-footer>
Home.scss
page-home { .item-row { width: 100%; height: 120px; } .image-background { border: 2px solid #222; background-color: rgba(92, 90, 87, 0.644); background-size: cover; background-position: center; background-repeat: no-repeat; height: 100%; } }
You can find the working project at Github
Emoticon Emoticon