diff --git a/components/globe-stats/index.js b/components/globe-stats/index.js new file mode 100644 index 0000000..bd3bc2c --- /dev/null +++ b/components/globe-stats/index.js @@ -0,0 +1,124 @@ +import createGlobe from "cobe"; + +import { useEffect, useRef, useState } from "react"; +import { useSpring } from "react-spring"; + +// Maybe dynamic based on device type? +const DPR = 1; + +export function GlobeStats() { + + + const canvasRef = useRef(); + const pointerInteracting = useRef(null); + const pointerInteractionMovement = useRef(0); + + const [{ r }, api] = useSpring(() => ({ + r: 0, + config: { + mass: 1, + tension: 280, + friction: 40, + precision: 0.001, + }, + })); + + useEffect(() => { + let phi = 0; + let width = 0; + const onResize = () => + canvasRef.current && (width = canvasRef.current.offsetWidth); + window.addEventListener("resize", onResize); + onResize(); + const globe = createGlobe(canvasRef.current, { + context: { + antialias: false, + }, + devicePixelRatio: DPR, + width: width * DPR, + height: width * DPR, + phi: 0, + theta: 0.3, + dark: 0, + diffuse: 3, + mapSamples: 20000, + mapBrightness: 2, + baseColor: [255 / 255, 220 / 255, 226 / 255], + markerColor: [200 / 255, 9 / 255, 76 / 255], + // rgb(200, 9, 76) + glowColor: [0.8*255 / 255, 0.8*220 / 255, 0.8*226 / 255], + markers: [ + // longitude latitude + { location: [37.7595, -122.4367], size: 0.03 }, + { location: [40.7128, -74.006], size: 0.1 } + ], + onRender: (state) => { + // Called on every animation frame. + // `state` will be an empty object, return updated params. + phi += 0.002; + state.phi = phi + r.get(); + state.width = width * DPR; + state.height = width * DPR; + }, + }); + setTimeout(() => (canvasRef.current.style.opacity = "1")); + return () => globe.destroy(); + }, []); + + return ( +
+ { + pointerInteracting.current = + e.clientX - pointerInteractionMovement.current; + canvasRef.current.style.cursor = "grabbing"; + }} + onPointerUp={() => { + pointerInteracting.current = null; + canvasRef.current.style.cursor = "grab"; + }} + onPointerOut={() => { + pointerInteracting.current = null; + canvasRef.current.style.cursor = "grab"; + }} + onMouseMove={(e) => { + if (pointerInteracting.current !== null) { + const delta = e.clientX - pointerInteracting.current; + pointerInteractionMovement.current = delta; + api.start({ + r: delta / 200, + }); + } + }} + onTouchMove={(e) => { + if (pointerInteracting.current !== null && e.touches[0]) { + const delta = e.touches[0].clientX - pointerInteracting.current; + pointerInteractionMovement.current = delta; + api.start({ + r: delta / 100, + }); + } + }} + style={{ + width: "100%", + height: "100%", + contain: "layout paint size", + opacity: 0, + transition: "opacity 1s ease", + }} + width="200" + height="200" + aspectRatio="1" + /> +
+ ); +} diff --git a/package.json b/package.json index 810a0e9..3b6947a 100644 --- a/package.json +++ b/package.json @@ -9,13 +9,15 @@ "lint": "next lint" }, "dependencies": { + "cobe": "^0.6.2", "idb-keyval": "^6.2.0", "next": "12.1.4", "next-pwa": "^5.6.0", "normalize.css": "^8.0.1", "react": "18.0.0", "react-dom": "18.0.0", - "react-rough-notation": "^1.0.2" + "react-rough-notation": "^1.0.2", + "react-spring": "^9.5.4" }, "devDependencies": { "eslint": "8.13.0", diff --git a/pages/index.js b/pages/index.js index c6a4f59..66286eb 100644 --- a/pages/index.js +++ b/pages/index.js @@ -7,6 +7,7 @@ import { RoughNotation } from "react-rough-notation"; import { data } from "../data"; import { SEO } from "../components/seo"; +import { GlobeStats } from "../components/globe-stats"; import dynamic from "next/dynamic"; @@ -40,24 +41,30 @@ export default function Home() {

- Always remember what is{" "} + Today, you joined 10K people in remembering what is + always {" "} - + true - {" "} + {" "} about you:

+
+ +
+
{Object.values(data) .filter((item) => !item.hide) .map((item) => ( -

- {item.title} -

+

{item.title}

{item.teaser}

diff --git a/styles/Home.module.css b/styles/Home.module.css index 837c9d5..94fc0e2 100644 --- a/styles/Home.module.css +++ b/styles/Home.module.css @@ -65,7 +65,9 @@ } .description { - margin: 4rem 0; + margin-top: 4rem; + margin-bottom: 0rem; + /* margin: 4rem 0; */ line-height: 1.5; font-size: 1.5rem; } @@ -146,3 +148,16 @@ top: 24px; right: 2px; } + +.globeStatsContainer { + position: relative; + width: 40%; + aspect-ratio: 1; +} +@media (max-width: 600px) { + .globeStatsContainer { + width: 115%; + } +} + + diff --git a/yarn.lock b/yarn.lock index 33e1160..cdec79d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1097,6 +1097,92 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@react-spring/animated@~9.5.4": + version "9.5.4" + resolved "https://registry.yarnpkg.com/@react-spring/animated/-/animated-9.5.4.tgz#4fb2114c5b68243fc451d9af33f5dadd5b3b1c42" + integrity sha512-gYd+xWwcNxEGA9EdORz/xsGsuQmz46FCu7OLIGOZK00fiSkjEM8yTwBQ9i8SUslRAdxTW+POL5OctDpCA6A7xw== + dependencies: + "@react-spring/shared" "~9.5.4" + "@react-spring/types" "~9.5.4" + +"@react-spring/core@~9.5.4": + version "9.5.4" + resolved "https://registry.yarnpkg.com/@react-spring/core/-/core-9.5.4.tgz#3bfdaf40ff34cd2659c1d11c88dd0e3575701920" + integrity sha512-ZQxS5+5i6dVWL8mnRbrUMdkT7TfWhdIYYe2ze3my2SNAKC14JjxHxeknX57ywRyudskR1Z9CQjiC8aXX6QBl7w== + dependencies: + "@react-spring/animated" "~9.5.4" + "@react-spring/rafz" "~9.5.4" + "@react-spring/shared" "~9.5.4" + "@react-spring/types" "~9.5.4" + +"@react-spring/konva@~9.5.4": + version "9.5.4" + resolved "https://registry.yarnpkg.com/@react-spring/konva/-/konva-9.5.4.tgz#f9e8213cd3dc6fb025b1b61996c77e146a321236" + integrity sha512-2myKIYXdApmdXDmvYcv/d85xHb7pLHKDJvE5fT+7qWYgCTtz9euUIaWWTkAbL0Sq9k55AB6RKT04p+xmu2PXGw== + dependencies: + "@react-spring/animated" "~9.5.4" + "@react-spring/core" "~9.5.4" + "@react-spring/shared" "~9.5.4" + "@react-spring/types" "~9.5.4" + +"@react-spring/native@~9.5.4": + version "9.5.4" + resolved "https://registry.yarnpkg.com/@react-spring/native/-/native-9.5.4.tgz#ab221df8124bc8d7e4427ffcb7310e065ef52df2" + integrity sha512-EVjAA++fBKW3RX++XJHUs5BYYd91kavjpYoHh75v8xV9td6GCgFBUw9P8zAeU1Hfe1ze4VWPcXgkhLX/g2e4ag== + dependencies: + "@react-spring/animated" "~9.5.4" + "@react-spring/core" "~9.5.4" + "@react-spring/shared" "~9.5.4" + "@react-spring/types" "~9.5.4" + +"@react-spring/rafz@~9.5.4": + version "9.5.4" + resolved "https://registry.yarnpkg.com/@react-spring/rafz/-/rafz-9.5.4.tgz#a2a036cb3e948c4f2a4be4d59e53857550c03db7" + integrity sha512-Tmev2j7sq2FW3ISUClnNS0PhkCsBfPPpkHVMxz8mkIKzMGXWskd0GblOoPVJiWvhbccaX/NYd+ykJqJ1gY0v9g== + +"@react-spring/shared@~9.5.4": + version "9.5.4" + resolved "https://registry.yarnpkg.com/@react-spring/shared/-/shared-9.5.4.tgz#0ae556047274997b87979df7ac27c29c58f590b3" + integrity sha512-22IYmNOzDRP9e5BaQk6T/P2aRxne9uTzGDYuBQCbJpChZypB98xWBMKlVTKdSRG7K4v+F97KFPAKBQzS/k7p5Q== + dependencies: + "@react-spring/rafz" "~9.5.4" + "@react-spring/types" "~9.5.4" + +"@react-spring/three@~9.5.4": + version "9.5.4" + resolved "https://registry.yarnpkg.com/@react-spring/three/-/three-9.5.4.tgz#8b461d60a05f205468ff19674e8e29509ba14521" + integrity sha512-grbkmBKuKyTdhDsGiSbFoKMhknJa2BwKo6sfbWjyypTpoJLXQAvW2GXmSgbcis1vLp19VrWy7zRqTJS5CZgkhQ== + dependencies: + "@react-spring/animated" "~9.5.4" + "@react-spring/core" "~9.5.4" + "@react-spring/shared" "~9.5.4" + "@react-spring/types" "~9.5.4" + +"@react-spring/types@~9.5.4": + version "9.5.4" + resolved "https://registry.yarnpkg.com/@react-spring/types/-/types-9.5.4.tgz#6d26df992a32ea5532a1e7b732f5485857116b00" + integrity sha512-dzcGxqL1kPKociXK+pcq5ley77cWDWiphfv8OREv8dAZS1dKDTJq1zVy7ZD5ocyMtKMZw/7AcOdIJ1H80Dp56g== + +"@react-spring/web@~9.5.4": + version "9.5.4" + resolved "https://registry.yarnpkg.com/@react-spring/web/-/web-9.5.4.tgz#ea46780761deb4c5a42dcc9745c2a121f8229a66" + integrity sha512-HoypE3kL/ZUBB81hThE1hB9jYBgJmfeluEOPYoI/wGHyF1q8O0AYpWClvdAbiK3FTESHYZi2m60jwitF7VYUlQ== + dependencies: + "@react-spring/animated" "~9.5.4" + "@react-spring/core" "~9.5.4" + "@react-spring/shared" "~9.5.4" + "@react-spring/types" "~9.5.4" + +"@react-spring/zdog@~9.5.4": + version "9.5.4" + resolved "https://registry.yarnpkg.com/@react-spring/zdog/-/zdog-9.5.4.tgz#078592e7a473cc01493e7f0d8712df96b93f1a72" + integrity sha512-4B0LxvoSrJKy3cEGLzwpeyGKXASJQAdlBB1BLj4l7RsbKfGAXR40VLuwhJVLYiYgUjJ9vur1i33R2qrTzJkrZA== + dependencies: + "@react-spring/animated" "~9.5.4" + "@react-spring/core" "~9.5.4" + "@react-spring/shared" "~9.5.4" + "@react-spring/types" "~9.5.4" + "@rollup/plugin-babel@^5.2.0": version "5.3.1" resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283" @@ -1521,6 +1607,13 @@ clean-webpack-plugin@^4.0.0: dependencies: del "^4.1.1" +cobe@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/cobe/-/cobe-0.6.2.tgz#dd236999ff5193d64ad780726e3023f3687b0239" + integrity sha512-0lU+QD18yzxsWsuTy4HB+kRYT/SugVPRx95MhfteZgD2UgEJ+6fScChroCVqIXWi5IxL0T8Ywm8avHvmOsl5xQ== + dependencies: + phenomenon "^1.6.0" + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -2932,6 +3025,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +phenomenon@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/phenomenon/-/phenomenon-1.6.0.tgz#7b5b7647d0b48152cc0846994da3d92e8f6da677" + integrity sha512-7h9/fjPD3qNlgggzm88cY58l9sudZ6Ey+UmZsizfhtawO6E3srZQXywaNm2lBwT72TbpHYRPy7ytIHeBUD/G0A== + picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -3036,6 +3134,18 @@ react-rough-notation@^1.0.2: dependencies: rough-notation "^0.4.0" +react-spring@^9.5.4: + version "9.5.4" + resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-9.5.4.tgz#4c67e33650292b79bceef611e4f0d36e74d08202" + integrity sha512-CelndH5CfAhiitqc2BbJ4b7DBou5M8qX2NMnc3vBHJIhp1Dp7KMA5nGCEtj9M9xOtCIpbPwB5XWbjttCDXOL4g== + dependencies: + "@react-spring/core" "~9.5.4" + "@react-spring/konva" "~9.5.4" + "@react-spring/native" "~9.5.4" + "@react-spring/three" "~9.5.4" + "@react-spring/web" "~9.5.4" + "@react-spring/zdog" "~9.5.4" + react@18.0.0: version "18.0.0" resolved "https://registry.yarnpkg.com/react/-/react-18.0.0.tgz#b468736d1f4a5891f38585ba8e8fb29f91c3cb96"