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:
parent
53519b7d8a
commit
0cfa60143a
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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){}
|
||||||
}
|
}
|
@ -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>
|
|
@ -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{
|
||||||
|
65
frontend/app/gallery/grid/GridRowBuilder.ts
Normal file
65
frontend/app/gallery/grid/GridRowBuilder.ts
Normal 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);
|
||||||
|
};
|
||||||
|
}
|
7
frontend/app/gallery/grid/grid.gallery.component.css
Normal file
7
frontend/app/gallery/grid/grid.gallery.component.css
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
div {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
gallery-photo {
|
||||||
|
display: inline-block;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
13
frontend/app/gallery/grid/grid.gallery.component.html
Normal file
13
frontend/app/gallery/grid/grid.gallery.component.html
Normal 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>
|
75
frontend/app/gallery/grid/grid.gallery.component.ts
Normal file
75
frontend/app/gallery/grid/grid.gallery.component.ts
Normal 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){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
<img [src]="getPhotoPath()" width="200px">
|
<img [src]="getPhotoPath()" style="width: inherit; height: inherit">
|
@ -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",
|
||||||
|
@ -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",
|
||||||
|
Loading…
Reference in New Issue
Block a user