Updated gallery
All checks were successful
Build Website / Build NPM Project (push) Successful in 1m44s
Build Website / Tag Version (push) Successful in 11s
Build Website / Build & Push Dockerfile (push) Successful in 2m40s

This commit is contained in:
2024-01-12 12:04:59 -05:00
parent 905f734d91
commit e6ff564111
14 changed files with 472 additions and 155 deletions

View File

@ -0,0 +1,16 @@
<div class="carousel-container" [style.height]="height" style="background: #282d31">
<div class="carousel-previous" (click)="previous()">
<mat-icon>keyboard_arrow_left</mat-icon>
</div>
<div *ngIf="loading" class="carousel-loading">
<div class="lds-ring"><div></div><div></div><div></div><div></div></div>
</div>
<img class="carousel-image" [src]="photos[index].src" [alt]="photos[index].alt || 'slide ' + index" (load)="loading = false">
<div class="carousel-next" (click)="next()">
<mat-icon>keyboard_arrow_right</mat-icon>
</div>
<div *ngIf="!disableAutoplay" class="carousel-pause" (click)="pause = !pause">
<mat-icon *ngIf="!pause">pause</mat-icon>
<mat-icon *ngIf="pause">play_arrow</mat-icon>
</div>
</div>

View File

@ -0,0 +1,117 @@
.carousel-container {
position: relative;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
.carousel-background {
width: 100%;
height: 100%;
filter: blur(10px);
-webkit-filter: blur(10px);
}
.carousel-loading {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
.lds-ring {
display: inline-block;
position: relative;
width: 80px;
height: 80px;
}
.lds-ring div {
box-sizing: border-box;
display: block;
position: absolute;
width: 64px;
height: 64px;
margin: 8px;
border: 8px solid #fff;
border-radius: 50%;
animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
border-color: #fff transparent transparent transparent;
}
.lds-ring div:nth-child(1) {
animation-delay: -0.45s;
}
.lds-ring div:nth-child(2) {
animation-delay: -0.3s;
}
.lds-ring div:nth-child(3) {
animation-delay: -0.15s;
}
@keyframes lds-ring {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
}
.carousel-image {
display: block;
max-width: 70%;
max-height: 90%;
object-fit: cover;
width: auto;
height: auto;
}
.carousel-next, .carousel-previous {
position: absolute;
top: 50%;
width: 56px;
height: 56px;
display: flex;
align-items: center;
justify-content: center;
color: rgba(255, 255, 255, 0.75);
filter: drop-shadow(3px 3px 5px black);
cursor: pointer;
transition: 0.25s;
border-radius: 50%;
transform: translateY(-50%);
&.carousel-next {
right: 0;
}
&.carousel-previous {
left: 0;
}
&:hover {
color: white;
background: rgba(0,0,0,0.25);
filter: none;
}
}
.carousel-pause {
position: absolute;
bottom: 0;
left: 50%;
height: 56px;
width: 56px;
transform: translate(-50%, -50%);
color: rgba(255, 255, 255, 0.75);
filter: drop-shadow(3px 3px 5px black);
cursor: pointer;
padding: 1rem;
border-radius: 50%;
transition: 0.25s;
&:hover {
color: white;
background: rgba(0,0,0,0.25);
filter: none;
}
}
}

View File

@ -0,0 +1,51 @@
import {AfterViewInit, Component, Input, OnDestroy, OnInit} from '@angular/core';
import {Photo} from '../models/photo';
@Component({
selector: 'xxx-carousel',
templateUrl: './carousel.component.html',
styleUrls: ['./carousel.component.scss']
})
export class CarouselComponent implements OnDestroy, OnInit, AfterViewInit {
private timer?: any;
loading = true;
@Input() background = true;
@Input() photos: Photo[] = [];
@Input() speed = 5000;
@Input() pause = false;
@Input() disableAutoplay = false;
@Input() index = ~~(Math.random() * this.photos.length);
@Input() height = '100%';
ngOnInit() {
if(this.disableAutoplay) this.pause = true;
}
ngAfterViewInit() {
this.timer = setInterval(() => {
if(!this.pause) this.next(false);
}, this.speed);
}
ngOnDestroy() {
if(this.timer) {
clearInterval(this.timer);
this.timer = null;
}
}
next(pause = true) {
this.loading = true;
this.pause = pause;
this.index++;
if(this.index >= this.photos.length) this.index = 0;
}
previous(pause = true) {
this.loading = true;
this.pause = pause;
this.index = this.index > 0 ? this.index - 1 : this.photos.length - 1;
}
}

View File

@ -0,0 +1,41 @@
import {Component, Inject} from '@angular/core';
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
import {Photo} from '../models/photo';
export interface ImageViewerOptions {
photos: Photo[],
index?: number;
}
@Component({
selector: 'xxx-viewer',
styles: [`
.close {
position: absolute;
top: 1rem;
right: 1rem;
z-index: 100000;
}
::ng-deep .cdk-overlay-pane {
max-width: 100% !important;
}
::ng-deep mat-dialog-container {
padding: 0 !important;
}
`],
template: `
<button class="close" mat-icon-button aria-label="close dialog" mat-dialog-close>
<mat-icon>close</mat-icon>
</button>
<xxx-carousel [photos]="photos" [index]="index" [disableAutoplay]="true"></xxx-carousel>
`
})
export class ImageViewerComponent {
index!: number;
photos!: Photo[];
constructor(public ref: MatDialogRef<ImageViewerComponent>, @Inject(MAT_DIALOG_DATA) data: ImageViewerOptions) {
this.index = data.index || 0;
this.photos = data.photos || [];
}
}

View File

@ -0,0 +1,4 @@
export interface Photo {
alt: string;
src: string;
}

View File

@ -0,0 +1,43 @@
import {Component, Input} from '@angular/core';
@Component({
selector: 'xxx-placeholder',
styles: [`
.placeholder {
position: relative;
background-color: #bbbbbb;
background: linear-gradient(to right, #eeeeee 8%, #bbbbbb 18%, #eeeeee 33%);
background-size: 400% 100%;
min-height: 100px;
min-width: 200px;
animation-duration: 3s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-name: placeHolderShimmer;
animation-timing-function: linear;
@keyframes placeHolderShimmer {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}
}
`],
template: `
<div *ngIf="loading" class="placeholder" [style.height]="height" [style.width]="width"></div>
<img [src]="src" [alt]="alt" [style]="style" [style.height]="height" [style.width]="width" loading="lazy" (load)="loading = false" />
`
})
export class PlaceholderComponent {
loading = true;
@Input() alt?: string;
@Input() src!: string;
@Input() style!: string;
@Input() height: string = 'auto';
@Input() width: string = 'auto';
}