Copy everything

This commit is contained in:
schmelczerandras 2020-08-12 10:52:09 +02:00 committed by schmelczerandras
commit 8526739939
68 changed files with 1075 additions and 0 deletions

View file

@ -0,0 +1,22 @@
import { ResponsiveImage } from '../model/responsive-image';
import { last } from './last';
export const createImage = (
image: ResponsiveImage,
alt: string,
tabIndex: number,
imageScreenRatio = 0.25
): HTMLImageElement => {
const img = new Image(image.width, image.height);
img.tabIndex = tabIndex;
img.srcset = image.srcSet;
img.sizes =
image.images
.map(d => `(max-width: ${d.width / imageScreenRatio}px) ${d.width}px,`)
.join('\n') + `\n${last(image.images).width}px`;
img.src = last(image.images)?.path;
img.alt = alt;
return img;
};

2
src/helper/last.ts Normal file
View file

@ -0,0 +1,2 @@
export const last = <T>(list: ArrayLike<T>): T =>
list.length >= 1 ? list[list.length - 1] : undefined;

24
src/index.html Normal file
View file

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Photos - András Schmelczer</title>
<meta name="description" content="A very simple page where I showcase some of my photos. Although I am not a professional photographer, I truly love capturing joyous moments.">
<meta name="theme-color" content="#A63446">
<meta name="viewport" content="initial-scale=1.0" />
<link href="https://fonts.googleapis.com/css?family=Roboto:100" rel="stylesheet">
</head>
<body>
<header>
<h1>András Schmelczer</h1>
</header>
<main id="images">
<section id="portraits" class="cluster"></section>
<div id="frame-container">
<img src="" alt="opened photo" id="frame-image"/>
</div>
<section id="landscapes" class="cluster"></section>
</main>
</body>
</html>

239
src/index.scss Normal file
View file

@ -0,0 +1,239 @@
@mixin center-children() {
display: flex;
justify-content: center;
align-items: center;
}
@mixin portrait() {
@media (max-width: 900px) {
@content;
}
}
@mixin landscape() {
@media (min-width: 900px) {
@content;
}
}
$text-color: #ffffff;
$accent-color: #a63446;
$background-color: #eeeeee;
$border-width: 5px;
$normal-margin: 24px;
$small-margin: 6px;
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:focus {
outline: $accent-color solid $border-width * 1.1;
outline-offset: -$border-width * 1.1;
}
img {
border: $border-width solid $text-color;
box-sizing: content-box;
width: 100%;
height: auto;
display: block;
}
html {
height: 100%;
overflow-x: hidden;
background-color: $background-color;
body {
display: flex;
overflow: hidden;
@include portrait {
height: 100%;
flex-direction: column;
}
@include landscape {
&::-webkit-scrollbar-track,
&::-webkit-scrollbar {
background-color: transparent;
width: 12px;
}
&::-webkit-scrollbar-thumb {
background-color: $accent-color;
border-radius: 1000px;
}
}
h1,
header {
font-family: 'Roboto', serif;
font-weight: 100;
@include landscape {
font-size: 3rem;
}
@include portrait {
font-size: 2rem;
}
}
header {
@include center-children;
box-sizing: content-box;
height: 100%;
position: relative;
@include portrait {
width: 100%;
height: 2.15ch;
padding: $normal-margin 0;
}
@include landscape {
width: 2.15ch;
height: 100vh;
padding: 0 $normal-margin;
}
h1 {
color: $text-color;
background-color: $accent-color;
padding: $normal-margin 0;
white-space: nowrap;
user-select: none;
z-index: 2;
position: fixed;
text-align: center;
@include portrait {
width: 100%;
}
@include landscape {
width: 101vh;
transform: rotate(-90deg);
}
}
}
main#images {
flex: 1;
display: flex;
justify-content: space-between;
@include portrait {
flex-direction: column;
}
.cluster {
display: flex;
justify-content: space-between;
img {
cursor: pointer;
}
&#portraits > img {
@include portrait {
height: 12vmin;
width: auto;
}
@include landscape {
width: 8vmin;
}
}
&#landscapes > img {
@include portrait {
height: 8vmin;
width: auto;
}
@include landscape {
width: 12vmin;
}
}
img {
@include portrait {
margin: 0 $small-margin;
}
}
@include portrait {
width: 100%;
overflow: auto;
margin: $small-margin 0;
padding: $small-margin 0;
object-fit: contain;
:first-child {
margin-left: 2 * $small-margin;
}
&:last-child {
margin-right: 2 * $small-margin !important;
}
}
@include landscape {
flex-direction: column;
margin: $normal-margin;
img {
margin: $small-margin 0;
}
:first-child {
margin-top: 0;
}
:last-child {
margin-bottom: 0;
}
}
}
#frame-container {
@include center-children;
margin: 0 $border-width;
flex: 1;
@include landscape {
}
@include portrait {
position: relative;
}
img {
height: auto;
width: auto;
top: 50%;
transform: translateY(-50%) translateX(-50%);
@include portrait {
position: absolute;
box-sizing: border-box;
max-width: 100% !important; // undo js
max-height: 100%;
left: 50% !important; // undo js
}
@include landscape {
position: fixed;
max-height: 90vh;
}
}
}
}
}
}

33
src/index.ts Normal file
View file

@ -0,0 +1,33 @@
import './index.scss';
import { Photos } from './photos';
// @ts-ignore
const images = require.context('./pictures', true, /.jpg$/);
const imagePath = name => images(name, true);
const addSupportForTabNavigation = () =>
(document.onkeydown = e => {
if (e.key === ' ') {
(document.activeElement as HTMLElement)?.click();
e.preventDefault();
}
});
const sizeFrame = () => {
const container = document.querySelector('#frame-container') as HTMLElement;
const image = container.querySelector('img');
image.style.maxWidth = container.clientWidth + 'px';
image.style.left = container.offsetLeft + container.clientWidth / 2 + 'px';
};
new Photos(
images.keys().map(k => imagePath(k)),
document.querySelector('#landscapes'),
document.querySelector('#portraits'),
document.querySelector('#frame-image')
);
addSupportForTabNavigation();
window.addEventListener('resize', sizeFrame);
sizeFrame();

View file

@ -0,0 +1,12 @@
export type ResponsiveImage = {
srcSet: string;
src: string;
placeholder: string;
width: number;
height: number;
images: Array<{
path: string;
width: number;
height: number;
}>;
};

109
src/photos.ts Normal file
View file

@ -0,0 +1,109 @@
import { ResponsiveImage } from './model/responsive-image';
import { createImage } from './helper/create-image';
export class Photos {
private readonly images: Array<HTMLImageElement>;
private _selectedId: number;
private timerId: NodeJS.Timeout = null;
private shouldNotChange = false;
public constructor(
images: Array<ResponsiveImage>,
private readonly landscapesContainer: HTMLElement,
private readonly portraitsContainer: HTMLElement,
private readonly pictureFrame: HTMLImageElement
) {
this.images = this.convertImages(images);
this.placeImages();
this.addEventListeners();
this.startAutoChange();
this.selectedId = 0;
}
private get selectedId(): number {
return this._selectedId;
}
private set selectedId(value: number) {
if (value < 0) {
value += this.images.length - 1;
}
this._selectedId = value % this.images.length;
this.loadToFrame(this.images[this.selectedId]);
this.images[this.selectedId].focus();
this.shouldNotChange = true;
}
private convertImages(images: Array<ResponsiveImage>) {
let portraits = 0; // evens
let landscapes = 1; // odds
const imgs = images.map((image, i) =>
createImage(
image,
'a photo',
Photos.isLandscape(image) ? (landscapes += 2) : (portraits += 2)
)
);
return imgs.sort((a, b) => a.tabIndex - b.tabIndex);
}
private placeImages() {
this.images.forEach(img => {
if (Photos.isLandscape(img)) {
img.classList.add('landscape');
this.landscapesContainer.appendChild(img);
} else {
img.classList.add('portrait');
this.portraitsContainer.appendChild(img);
}
});
}
private addEventListeners() {
window.document.addEventListener('keydown', e => {
switch (e.key) {
case 'ArrowLeft':
this.selectedId--;
break;
case 'ArrowRight':
this.selectedId++;
break;
case 'Tab':
if (this.timerId !== null) {
clearInterval(this.timerId);
this.timerId = null;
}
}
});
window.document.addEventListener(
'scroll',
() => (this.shouldNotChange = true)
);
this.images.forEach((image, i) =>
image.addEventListener('click', () => (this.selectedId = i))
);
}
private startAutoChange() {
this.timerId = setInterval(() => {
if (!this.shouldNotChange) {
this.selectedId++;
}
this.shouldNotChange = false;
}, 7000);
}
private loadToFrame(img: HTMLImageElement) {
this.pictureFrame.src = img.src;
}
private static isLandscape(
image: HTMLImageElement | ResponsiveImage
): boolean {
return image.width > image.height;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

BIN
src/pictures/_DSC1484.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 MiB

BIN
src/pictures/_DSC1834.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

BIN
src/pictures/_DSC2313.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

BIN
src/pictures/_DSC2362.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

BIN
src/pictures/_DSC2674.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
src/pictures/_DSC2692.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 MiB

BIN
src/pictures/adam.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

BIN
src/pictures/dorka-1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 MiB

BIN
src/pictures/nap-2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 MiB

BIN
src/pictures/web-1-2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

BIN
src/pictures/web-1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

BIN
src/pictures/web-10.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

BIN
src/pictures/web-11.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

BIN
src/pictures/web-12.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

BIN
src/pictures/web-13.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

BIN
src/pictures/web-14.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

BIN
src/pictures/web-17.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

BIN
src/pictures/web-18.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 KiB

BIN
src/pictures/web-19.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 KiB

BIN
src/pictures/web-2-2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 KiB

BIN
src/pictures/web-2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 KiB

BIN
src/pictures/web-20.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

BIN
src/pictures/web-22.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

BIN
src/pictures/web-23.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 KiB

BIN
src/pictures/web-24.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

BIN
src/pictures/web-25.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

BIN
src/pictures/web-26.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 KiB

BIN
src/pictures/web-3-2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 KiB

BIN
src/pictures/web-3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

BIN
src/pictures/web-4-2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 KiB

BIN
src/pictures/web-42.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
src/pictures/web-5.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

BIN
src/pictures/web-6.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 KiB

BIN
src/pictures/web-7.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 KiB

BIN
src/pictures/web-8.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 KiB