1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2024-12-27 02:09:16 +02:00

implementing responsive photo grid system

This commit is contained in:
Braun Patrik 2016-04-09 15:19:25 +02:00
parent 53519b7d8a
commit 0cfa60143a
11 changed files with 170 additions and 7 deletions

View File

@ -1,6 +1,7 @@
import * as fs from 'fs'; import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
import * as mime from 'mime'; import * as mime from 'mime';
import * as sizeOf from 'image-size';
import {Directory} from "../../common/entities/Directory"; import {Directory} from "../../common/entities/Directory";
import {Photo} from "../../common/entities/Photo"; import {Photo} from "../../common/entities/Photo";
@ -30,7 +31,8 @@ export class GalleryManager {
} }
if(GalleryManager.isImage(fullFilePath)){ if(GalleryManager.isImage(fullFilePath)){
directory.photos.push(new Photo(1,file)); let dimensions = sizeOf(fullFilePath);
directory.photos.push(new Photo(1,file,dimensions.width,dimensions.height));
} }
} }

View File

@ -1,4 +1,4 @@
export class Photo{ export class Photo{
constructor(public id:number,public name:string){} constructor(public id:number,public name:string,public width:number,public height:number){}
} }

View File

@ -3,6 +3,4 @@
<div *ngIf="currentDirectory" *ngFor="#directory of currentDirectory.directories" > <div *ngIf="currentDirectory" *ngFor="#directory of currentDirectory.directories" >
<gallery-directory *ngIf="directory" [directory]="directory" ></gallery-directory> <gallery-directory *ngIf="directory" [directory]="directory" ></gallery-directory>
</div> </div>
<div *ngIf="currentDirectory" *ngFor="#photo of currentDirectory.photos" > <gallery-grid [directory]="currentDirectory"></gallery-grid>
<gallery-photo *ngIf="photo" [photo]="photo" [directory]="currentDirectory"></gallery-photo>
</div>

View File

@ -8,11 +8,12 @@ import {Directory} from "../../../common/entities/Directory";
import {Message} from "../../../common/entities/Message"; import {Message} from "../../../common/entities/Message";
import {GalleryPhotoComponent} from "./photo/photo.gallery.component"; import {GalleryPhotoComponent} from "./photo/photo.gallery.component";
import {GalleryDirectoryComponent} from "./directory/directory.gallery.component"; import {GalleryDirectoryComponent} from "./directory/directory.gallery.component";
import {GalleryGridComponent} from "./grid/grid.gallery.component";
@Component({ @Component({
selector: 'gallery', selector: 'gallery',
templateUrl: 'app/gallery/gallery.component.html', templateUrl: 'app/gallery/gallery.component.html',
directives:[GalleryPhotoComponent, directives:[GalleryGridComponent,
GalleryDirectoryComponent] GalleryDirectoryComponent]
}) })
export class GalleryComponent implements OnInit{ export class GalleryComponent implements OnInit{

View File

@ -0,0 +1,65 @@
import {Photo} from "../../../../common/entities/Photo";
export class GridRowBuilder{
private photoRow:Array<Photo> = [];
private photoIndex:number = 0; //index of the last pushed photo to the photoRow
constructor(private photos:Array<Photo>, private startIndex:number, private photoMargin:number, private containerWidth:number){
this.photoIndex = startIndex;
}
public addPhotos(number:number){
for(let i = 0; i < number; i++){
this.addPhoto();
}
}
public addPhoto():boolean{
if(this.photoIndex + 1 > this.photos.length){
return false;
}
this.photoRow.push(this.photos[this.photoIndex]);
this.photoIndex++;
return true;
}
public removePhoto():boolean{
if(this.photoIndex - 1 < this.startIndex){
return false;
}
this.photoIndex--;
this.photoRow.pop();
return true;
}
public getPhotoRow():Array<Photo>{
return this.photoRow;
}
public adjustRowHeightBetween(minHeight:number,maxHeight:number){
while (this.calcRowHeight() > maxHeight && this.addPhoto() === true) { //row too high -> add more images
}
while (this.calcRowHeight() < minHeight && this.removePhoto() === true) { //roo too small -> remove images
}
//keep at least one photo int thr row
if(this.photoRow.length <= 0){
this.addPhoto();
}
}
public calcRowHeight():number {
let width = 0;
for(let i = 0; i < this.photoRow.length; i++){
width += ((this.photoRow[i].width) / (this.photoRow[i].height)); //summing up aspect ratios
}
let height = (this.containerWidth - this.photoRow.length * (this.photoMargin * 2) - 1) / width; //cant be equal -> width-1
return height +(this.photoMargin * 2);
};
}

View File

@ -0,0 +1,7 @@
div {
display: block;
}
gallery-photo {
display: inline-block;
overflow: hidden;
}

View File

@ -0,0 +1,13 @@
<div *ngIf="directory" (window:resize)="onResize()">
<gallery-photo
*ngFor="#gridPhoto of photosToRender"
*ngIf="gridPhoto"
[photo]="gridPhoto.photo"
[directory]="directory"
[style.width.px]="gridPhoto.renderWidth"
[style.height.px]="gridPhoto.renderHeight"
[style.marginLeft.px]="IMAGE_MARGIN"
[style.marginRight.px]="IMAGE_MARGIN">
</gallery-photo>
</div>

View File

@ -0,0 +1,75 @@
///<reference path="../../../browser.d.ts"/>
import {Component, Input, ElementRef, OnChanges} from 'angular2/core';
import {Directory} from "../../../../common/entities/Directory";
import {Photo} from "../../../../common/entities/Photo";
import {GalleryPhotoComponent} from "../photo/photo.gallery.component";
import {GridRowBuilder} from "./GridRowBuilder";
@Component({
selector: 'gallery-grid',
templateUrl: 'app/gallery/grid/grid.gallery.component.html',
styleUrls: ['app/gallery/grid/grid.gallery.component.css'],
directives:[GalleryPhotoComponent]
})
export class GalleryGridComponent implements OnChanges{
@Input() directory:Directory;
photosToRender:Array<GridPhoto> = [];
private IMAGE_MARGIN = 2;
private TARGET_COL_COUNT = 5;
private MIN_ROW_COUNT = 2;
private MAX_ROW_COUNT = 5;
constructor(private elementRef: ElementRef) {
}
ngOnChanges(){
this.renderPhotos();
}
private renderPhotos() {
let maxRowHeight = window.innerHeight / this.MIN_ROW_COUNT;
let minRowHeight = window.innerHeight / this.MAX_ROW_COUNT;
this.photosToRender = [];
let i = 0;
while (i < this.directory.photos.length ) {
let photoRowBuilder = new GridRowBuilder(this.directory.photos,i,this.IMAGE_MARGIN,this.getContainerWidth());
photoRowBuilder.addPhotos(this.TARGET_COL_COUNT);
photoRowBuilder.adjustRowHeightBetween(minRowHeight,maxRowHeight);
let rowHeight = photoRowBuilder.calcRowHeight();
let imageHeight = rowHeight - (this.IMAGE_MARGIN * 2);
photoRowBuilder.getPhotoRow().forEach((photo) => {
let imageWidth = imageHeight * (photo.width / photo.height);
this.photosToRender.push(new GridPhoto(photo,imageWidth,imageHeight));
});
i+= photoRowBuilder.getPhotoRow().length;
}
}
onResize() {
this.renderPhotos();
}
private getContainerWidth(): number{
if(typeof this.elementRef.nativeElement.firstElementChild === 'undefined' ||
this.elementRef.nativeElement.firstElementChild === null){
return 0;
}
return this.elementRef.nativeElement.firstElementChild.clientWidth;
}
}
class GridPhoto {
constructor(public photo:Photo, public renderWidth:number, public renderHeight:number){
}
}

View File

@ -1 +1 @@
<img [src]="getPhotoPath()" width="200px"> <img [src]="getPhotoPath()" style="width: inherit; height: inherit">

View File

@ -27,6 +27,7 @@
"debug": "^2.2.0", "debug": "^2.2.0",
"express": "^4.13.4", "express": "^4.13.4",
"express-session": "^1.13.0", "express-session": "^1.13.0",
"image-size": "^0.5.0",
"jimp": "^0.2.21", "jimp": "^0.2.21",
"mime": "^1.3.4", "mime": "^1.3.4",
"morgan": "^1.7.0", "morgan": "^1.7.0",

View File

@ -6,6 +6,7 @@
"debug": "github:DefinitelyTyped/DefinitelyTyped/debug/debug.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e", "debug": "github:DefinitelyTyped/DefinitelyTyped/debug/debug.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e",
"express": "github:DefinitelyTyped/DefinitelyTyped/express/express.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e", "express": "github:DefinitelyTyped/DefinitelyTyped/express/express.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e",
"express-session": "registry:dt/express-session#0.0.0+20160331200931", "express-session": "registry:dt/express-session#0.0.0+20160331200931",
"image-size": "registry:dt/image-size#0.0.0+20160223165602",
"jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#d22516f9f089de107d7e7d5938566377370631f6", "jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#d22516f9f089de107d7e7d5938566377370631f6",
"mime": "github:DefinitelyTyped/DefinitelyTyped/mime/mime.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e", "mime": "github:DefinitelyTyped/DefinitelyTyped/mime/mime.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e",
"node": "github:DefinitelyTyped/DefinitelyTyped/node/node.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e", "node": "github:DefinitelyTyped/DefinitelyTyped/node/node.d.ts#0d622d857f97d44ea7dcad2b3edec1f23c48fe9e",