aboutsummaryrefslogtreecommitdiff
path: root/static/pages/shuffle/index.js
blob: 7833de4cb92d64c45847a71cb14695b0601dd0ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import * as sfw from 'sfw';
const { Div, Canvas } = sfw.element.native;

import { Image } from 'widgets';

const css = await sfw.css(import.meta.url, './index.css');

export default class ShuffleView extends sfw.element.Container {
	#front_image
	#back_image
	#front_image_index
	#back_image_index
	#images
	#date
	#drag_start_position
	#drag_strength

	constructor() {
		super({ css });

		this.#front_image_index = null;
		this.#back_image_index = null;

		this.body.append(
			this.#date = Div.new({ id: 'date' }),
			this.#front_image = Image.new({
				id: 'front',
				disabled: true,
				ontouchstart: (e) => {
					if (e.touches.length != 1) return;

					this.#drag_start_position = [e.touches[0].pageX, e.touches[0].pageY];
				},
				ontouchmove: (e) => {
					if (e.touches.length != 1) return;

					const position = [e.touches[0].pageX, e.touches[0].pageY];

					const delta = [
						position[0] - this.#drag_start_position[0],
						position[1] - this.#drag_start_position[1]
					];

					const strength = Math.min(1, Math.max((delta[0]**2 + delta[1]**2) / (40 ** 2), 0) / 100);
					this.#drag_strength = strength;

					const angle_x = position[0] - window.screen.width / 2;
					const angle_y = position[1] - window.screen.height * 1.2;
					let angle = (Math.atan((angle_y) / (angle_x)) * 180 / Math.PI  + 90);

					if (angle_x < 0) {
						angle -= 180;
					}

					this.#front_image.style.transform = `
						translate(-50%, calc(-50% - 50px))
						translate(${delta[0]}px, ${delta[1]}px)
						rotate(${angle}deg)
					`;
					this.#back_image.style.filter = `blur(${(1 - strength) * 50}px)`;
				},
				ontouchend: (e) => {
					if (this.#drag_strength > 0.3) {
						this.next();
					}

					this.#front_image.style.transform = '';
					this.#back_image.style.filter = '';
				},
			}),
			this.#back_image = Image.new({ id: 'back', disabled: true }),
		)

		this.onclick = () => this.next();
	}

	set images(images) {
		this.#images = images;
	}

	open() {
		this.next();
		this.next();
	}

	next() {
		this.#front_image_index = this.#back_image_index;
		this.#back_image_index = Math.floor(Math.random() * this.#images.length);

		if (this.#front_image_index !== null) {
			this.#front_image.metadata = this.#images[this.#front_image_index];
			this.#front_image.load();

			const date = this.#images[this.#front_image_index].date
			
			this.#date.innerText = date.toLocaleString('default', {
				month: 'long',
				year: 'numeric',
				day: 'numeric',
				hour: 'numeric',
				minute: 'numeric'
			}); ;
		}

		this.#back_image.metadata = this.#images[this.#back_image_index];
		this.#back_image.load();
	}
}