summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/graph.js18
-rw-r--r--src/views/Clock.js108
-rw-r--r--src/views/Clocks.js15
-rw-r--r--src/views/Detail.js5
-rw-r--r--src/views/Legend.js17
5 files changed, 156 insertions, 7 deletions
diff --git a/src/graph.js b/src/graph.js
index a210f23..3a0e8a1 100644
--- a/src/graph.js
+++ b/src/graph.js
@@ -3,7 +3,9 @@ import ForceGraph3D from "3d-force-graph";
import SpriteText from "three-spritetext";
import { union } from "./utils/set_utils.js";
-const IMG_SCALE = 20;
+const IMG_SCALE = 16;
+const MAIN_IMG_SCALE = 80;
+const OBJECT_SCALE = 10;
export default function buildGraph({ db, objects, handlers }) {
const linkable = {};
@@ -85,7 +87,7 @@ export default function buildGraph({ db, objects, handlers }) {
var center = new THREE.Vector3();
box.getCenter(center);
object.position.sub(center);
- object.scale.set(100, 100, 100);
+ object.scale.set(OBJECT_SCALE, OBJECT_SCALE, OBJECT_SCALE);
return object;
} else if (node.data.thumbnail?.uri) {
if (node.data.thumbnail.type === "video") {
@@ -103,7 +105,11 @@ export default function buildGraph({ db, objects, handlers }) {
const aspect = node.data.thumbnail.width / node.data.thumbnail.height;
material = new THREE.SpriteMaterial({ map: texture });
sprite = new THREE.Sprite(material);
- sprite.scale.set(IMG_SCALE, IMG_SCALE / aspect);
+ if (node.id === 0) {
+ sprite.scale.set(MAIN_IMG_SCALE, MAIN_IMG_SCALE / aspect);
+ } else {
+ sprite.scale.set(IMG_SCALE, IMG_SCALE / aspect);
+ }
return sprite;
} else {
sprite = new SpriteText(
@@ -117,6 +123,12 @@ export default function buildGraph({ db, objects, handlers }) {
})
.onNodeClick(handlers.click);
+ // TrackballControls
+ graph.controls().addEventListener("change", () => {
+ const position = graph.cameraPosition();
+ // console.log(position);
+ });
+
const initialZoom = () => {
const distance = 20000;
let angle = 0;
diff --git a/src/views/Clock.js b/src/views/Clock.js
new file mode 100644
index 0000000..a394b62
--- /dev/null
+++ b/src/views/Clock.js
@@ -0,0 +1,108 @@
+/**
+ * Analog Clock
+ */
+
+import React, { useState, useEffect } from "react";
+
+const clock = {
+ width: "20vw",
+ height: "20vw",
+ background: "url(assets/img/clock/clock.png)",
+ backgroundSize: "contain",
+ backgroundPosition: "center center",
+ backgroundRepeat: "no-repeat",
+ position: "relative",
+};
+
+const handStyle = {
+ position: "absolute",
+ top: "0%",
+ left: "0%",
+};
+
+const hourStyle = {
+ ...handStyle,
+ height: "calc(540 / 1268 * 10vw)",
+ transformOrigin: "45.46% 96.62%",
+};
+
+const minuteStyle = {
+ ...handStyle,
+ height: "calc(795 / 1268 * 10vw)",
+ transformOrigin: "50% 84.05%",
+};
+
+const secondStyle = {
+ ...handStyle,
+ height: "calc(993 / 1268 * 10vw)",
+ transformOrigin: "45.83% 76.63%",
+};
+
+const hourTransform =
+ "translateX(10.45vw) translateY(10vw) translateX(-100%) translateY(-100%) ";
+const minuteTransform =
+ "translateX(10.45vw) translateY(10.8vw) translateX(-100%) translateY(-100%) ";
+const secondTransform =
+ "translateX(10.2vw) translateY(11.5vw) translateX(-100%) translateY(-100%) ";
+
+export default function Clock({ utc }) {
+ const [hour, setHour] = useState({});
+ const [minute, setMinute] = useState({});
+ const [second, setSecond] = useState({});
+
+ useEffect(() => {
+ const update = () => {
+ const time = new Date();
+ const hours = utc ? time.getUTCHours() : time.getHours();
+ const minutes = time.getMinutes();
+ const seconds = time.getSeconds();
+ const ms = time.getMilliseconds();
+ setHour({
+ ...hourStyle,
+ transform:
+ hourTransform +
+ "rotate(" +
+ (((hours % 12) + minutes / 60 + seconds / 3600) / 12) * 360 +
+ "deg)",
+ });
+ setMinute({
+ ...minuteStyle,
+ transform:
+ minuteTransform +
+ "rotate(" +
+ (minutes / 60 + seconds / 3600) * 360 +
+ "deg)",
+ });
+ setSecond({
+ ...secondStyle,
+ transform:
+ secondTransform +
+ "rotate(" +
+ (seconds / 60 + ms / 60000) * 360 +
+ "deg)",
+ });
+ };
+ update();
+ const intervalId = setInterval(update, 50);
+ return () => clearInterval(intervalId);
+ }, []);
+
+ return (
+ <div style={clock}>
+ <img src="assets/img/clock/hour.png" style={hour} />
+ <img src="assets/img/clock/minute.png" style={minute} />
+ <img src="assets/img/clock/second.png" style={second} />
+ </div>
+ );
+}
+
+// ratio: 500 / 1268
+// hour: 540
+// minute: 795
+// second: 993
+
+// hour transform origin: 40 x 515 // 88 / 533
+// minute transform origin: 37 x 622 // 72 x 740
+// second transform origin: 11 x 751 // 24 x 980
+
+const rand = (n) => Math.random() * n;
diff --git a/src/views/Clocks.js b/src/views/Clocks.js
new file mode 100644
index 0000000..d984f7b
--- /dev/null
+++ b/src/views/Clocks.js
@@ -0,0 +1,15 @@
+/**
+ * Two clocks
+ */
+
+import React from "react";
+import Clock from "./Clock.js";
+
+export default function Clocks() {
+ return (
+ <div className="clocks">
+ <Clock />
+ <Clock utc />
+ </div>
+ );
+}
diff --git a/src/views/Detail.js b/src/views/Detail.js
index ff6a6a5..b1c4dcf 100644
--- a/src/views/Detail.js
+++ b/src/views/Detail.js
@@ -5,6 +5,7 @@
import React from "react";
import Gallery from "./Gallery.js";
+import Clocks from "./Clocks.js";
import Vimeo from "@u-wave/react-vimeo";
export default function Detail({ node, visible, onClose }) {
@@ -39,7 +40,9 @@ export default function Detail({ node, visible, onClose }) {
<div className="buttons close">
<img src="/assets/img/close.svg" onClick={onClose} />
</div>
- {data.type === "video" ? (
+ {index === 33 ? (
+ <Clocks />
+ ) : data.type === "video" ? (
visible && (
<div className="video">
<Vimeo
diff --git a/src/views/Legend.js b/src/views/Legend.js
index fe7db4d..411ca81 100644
--- a/src/views/Legend.js
+++ b/src/views/Legend.js
@@ -4,9 +4,20 @@
import React, { useState, useEffect } from "react";
-const categories = "No6092,1620s,painting,blunt,National Gallery of Canada,AGO,courtauld,intervensions,connsoeurship,double agent,forensics,black box,Stankievech".split(
- ","
-);
+var categories = [
+ // tag ID = array offset + 1
+ "1620s",
+ "painting",
+ "blunt",
+ "National Gallery of Canada",
+ "Art Gallery of Ontario",
+ "Courtauld Institute",
+ "Stankievech",
+ "connsoeurship",
+ "double agent",
+ "forensics",
+ "black box",
+];
export default function Legend({ visible, selected, onSelect }) {
return (