aboutsummaryrefslogtreecommitdiff
path: root/static/pages/shuffle
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2025-12-17 21:33:06 +0100
committerNathan Reiner <nathan@nathanreiner.xyz>2025-12-17 21:33:06 +0100
commit9c37e114b20e6b2a2d4a34fe1f0e44c5ed3439ed (patch)
tree42f05bd826fb1e55e70a5402167521253bc8be86 /static/pages/shuffle
parent99701b8d6fc0671fabc2e5d3ab7d6841bff9021a (diff)
shuffle: first version
Diffstat (limited to 'static/pages/shuffle')
-rw-r--r--static/pages/shuffle/index.css42
-rw-r--r--static/pages/shuffle/index.js106
2 files changed, 136 insertions, 12 deletions
diff --git a/static/pages/shuffle/index.css b/static/pages/shuffle/index.css
index 8c9434e..30d30ac 100644
--- a/static/pages/shuffle/index.css
+++ b/static/pages/shuffle/index.css
@@ -1,11 +1,39 @@
+:host {
+ display: block;
+ width: 100vw;
+ height: 100vh;
+ top: 0px;
+ left: 0px;
+ overflow: hidden;
+ position: relative;
+}
-#container {
+sfw-image {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, calc(-50% - 50px));
width: 100%;
- height: 100%;
- background: var(--page-background);
- text-align: center;
- align-content: center;
- color: #838b97;
- font-family: 'Pacifico';
+ max-width: calc(100vw - 20px);
+ max-height: calc(100vh - 200px);
user-select: none;
+ transition: transform 0.05s ease;
+}
+
+#front {
+ z-index: 1000;
+}
+
+#back {
+ z-index: 500;
+ filter: blur(50px);
+}
+
+#date {
+ margin: 10px;
+ border-radius: var(--border-radius);
+ padding: 10px;
+ background: #efefef99;
+ backdrop-filter: blur(10px);
+ box-shadow: #223223aa 1px 1px 4px;
}
diff --git a/static/pages/shuffle/index.js b/static/pages/shuffle/index.js
index 7bfd33e..6d65788 100644
--- a/static/pages/shuffle/index.js
+++ b/static/pages/shuffle/index.js
@@ -1,17 +1,113 @@
import * as sfw from 'sfw';
-const { Div } = sfw.element.native;
+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(
- Div.new({
- id: 'container',
- innerText: 'Pure Emptiness',
- })
+ 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;
+ console.log(this.#drag_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.ondragover = (e) => {
+ console.log(e)
+ }
+
+ 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();
}
}