Add scrolling and pause button
This commit is contained in:
parent
54bc013531
commit
e3e9710f7a
|
@ -1,20 +1,33 @@
|
|||
import * as THREE from "three";
|
||||
import React, { Suspense } from "react";
|
||||
import { useLoader } from "@react-three/fiber";
|
||||
import React, { useRef, Suspense } from "react";
|
||||
import { useLoader, useFrame } from "@react-three/fiber";
|
||||
|
||||
interface ImagePlaneProps {
|
||||
url: string;
|
||||
};
|
||||
height: number;
|
||||
paused: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw an image on a plane geometry.
|
||||
*/
|
||||
export default function ImagePlane(props: ImagePlaneProps) {
|
||||
const texture = useLoader(THREE.TextureLoader, props.url);
|
||||
|
||||
const mesh = useRef<THREE.Mesh>(null);
|
||||
|
||||
useFrame(() => {
|
||||
if (props.paused) {
|
||||
return;
|
||||
}
|
||||
|
||||
mesh.current.position.y += 1 / 30.0;
|
||||
});
|
||||
|
||||
return (
|
||||
<Suspense fallback={null}>
|
||||
<mesh rotation-z={-Math.PI / 2}>
|
||||
<planeBufferGeometry attach="geometry" args={[150, 30]} />
|
||||
<mesh ref={mesh} rotation-z={-Math.PI / 2} position-y={props.height}>
|
||||
<planeBufferGeometry attach="geometry" args={[30, 30]} />
|
||||
<meshBasicMaterial attach="material" map={texture} />
|
||||
</mesh>
|
||||
</Suspense>
|
||||
|
|
|
@ -1,22 +1,23 @@
|
|||
import { NextComponentType } from 'next'
|
||||
import { Fragment, useState } from 'react'
|
||||
import { FiPause, FiPlay } from "react-icons/fi";
|
||||
|
||||
const Modal: NextComponentType = () => {
|
||||
const [paused, SetPause] = useState(false)
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
title="Pause"
|
||||
className="fixed z-90 top-28 right-8 bg-slate-100 w-14 h-14 rounded-full drop-shadow-lg
|
||||
interface PauseProps {
|
||||
paused: boolean;
|
||||
setPaused: (value: boolean) => void;
|
||||
}
|
||||
|
||||
const Pause = (props: PauseProps) => {
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
title="Pause"
|
||||
className="fixed z-90 top-28 right-8 bg-slate-100 w-14 h-14 rounded-full drop-shadow-lg
|
||||
flex justify-center items-center text-black text-2xl hover:bg-sky-500 hover:drop-shadow-2xl"
|
||||
onClick={() => SetPause(!paused)}
|
||||
>
|
||||
{paused ? <FiPlay /> : <FiPause />}
|
||||
</button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Modal
|
||||
onClick={() => props.setPaused(!props.paused)}
|
||||
>
|
||||
{props.paused ? <FiPlay /> : <FiPause />}
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Pause;
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
import { Dialog, Transition } from '@headlessui/react'
|
||||
import { NextComponentType } from 'next'
|
||||
import { Fragment, useState } from 'react'
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import { Fragment, useState } from "react";
|
||||
import { FiSliders } from "react-icons/fi";
|
||||
|
||||
|
||||
const Modal: NextComponentType = () => {
|
||||
const [open, setOpen] = useState(false)
|
||||
const Settings = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
title="Settings"
|
||||
className="fixed z-90 top-8 right-8 bg-slate-100 w-14 h-14 rounded-full drop-shadow-lg
|
||||
title="Settings"
|
||||
className="fixed z-90 top-8 right-8 bg-slate-100 w-14 h-14 rounded-full drop-shadow-lg
|
||||
flex justify-center items-center text-black text-2xl hover:bg-sky-500 hover:drop-shadow-2xl"
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
<FiSliders />
|
||||
</button>
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
<FiSliders />
|
||||
</button>
|
||||
|
||||
<Transition appear show={open} as={Fragment}>
|
||||
<Dialog
|
||||
|
@ -80,7 +78,7 @@ const Modal: NextComponentType = () => {
|
|||
</Dialog>
|
||||
</Transition>
|
||||
</>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default Modal
|
||||
export default Settings;
|
||||
|
|
|
@ -3,15 +3,28 @@ import { Canvas } from "@react-three/fiber";
|
|||
import RotatingBox from "./RotatingBox";
|
||||
import ImagePlane from "./ImagePlane";
|
||||
|
||||
interface CanvasProps {
|
||||
paused: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* React three fiber canvas with spectrogram drawing.
|
||||
*/
|
||||
export default function ThreeCanvas() {
|
||||
export default function ThreeCanvas(props: CanvasProps) {
|
||||
// change the image URL
|
||||
const spectrogram_image = "spectrogram.jpeg";
|
||||
|
||||
const height = -30.0;
|
||||
|
||||
return (
|
||||
<Canvas camera={{ position: [0, 0, 35] }}>
|
||||
<Canvas camera={{ position: [0, 0, 35], rotation: [0.2, 0, 0] }}>
|
||||
<ambientLight intensity={2} />
|
||||
<pointLight position={[40, 40, 40]} />
|
||||
<ImagePlane url={"spectrogram_example.png"} />
|
||||
<ImagePlane
|
||||
url={spectrogram_image}
|
||||
height={height}
|
||||
paused={props.paused}
|
||||
/>
|
||||
<RotatingBox position={[-12, 0, 1]} />
|
||||
<RotatingBox position={[-4, 0, 1]} />
|
||||
<RotatingBox position={[4, 0, 1]} />
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@headlessui/react": "^1.5.0",
|
||||
"@heroicons/react": "^1.0.5",
|
||||
"@react-three/drei": "^9.41.2",
|
||||
"@react-three/fiber": "^8.9.1",
|
||||
"eslint": "8.27.0",
|
||||
|
@ -119,14 +118,6 @@
|
|||
"react-dom": "^16 || ^17 || ^18"
|
||||
}
|
||||
},
|
||||
"node_modules/@heroicons/react": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@heroicons/react/-/react-1.0.6.tgz",
|
||||
"integrity": "sha512-JJCXydOFWMDpCP4q13iEplA503MQO3xLoZiKum+955ZCtHINWnx26CUxVxxFQu/uLb4LW3ge15ZpzIkXKkJ8oQ==",
|
||||
"peerDependencies": {
|
||||
"react": ">= 16"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.11.7",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.7.tgz",
|
||||
|
@ -4260,12 +4251,6 @@
|
|||
"client-only": "^0.0.1"
|
||||
}
|
||||
},
|
||||
"@heroicons/react": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@heroicons/react/-/react-1.0.6.tgz",
|
||||
"integrity": "sha512-JJCXydOFWMDpCP4q13iEplA503MQO3xLoZiKum+955ZCtHINWnx26CUxVxxFQu/uLb4LW3ge15ZpzIkXKkJ8oQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"@humanwhocodes/config-array": {
|
||||
"version": "0.11.7",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.7.tgz",
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
"eslint": "8.27.0",
|
||||
"eslint-config-next": "13.0.4",
|
||||
"@headlessui/react": "^1.5.0",
|
||||
"@heroicons/react": "^1.0.5",
|
||||
"next": "13.0.4",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
import Head from "next/head";
|
||||
import { useState } from "react";
|
||||
|
||||
|
||||
import ThreeCanvas from "../components/ThreeCanvas";
|
||||
import { FiPause } from "react-icons/fi";
|
||||
import Settings from '../components/Settings'
|
||||
import Pause from '../components/Pause'
|
||||
|
||||
export default function Home() {
|
||||
|
||||
const [paused, setPaused] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
|
@ -19,7 +23,7 @@ export default function Home() {
|
|||
|
||||
<div className="bg-sky-900 flex flex-row min-h-screen text-white">
|
||||
<div className="w-1/3 min-h-screen">
|
||||
<ThreeCanvas />
|
||||
<ThreeCanvas paused={paused} />
|
||||
</div>
|
||||
|
||||
<main className="w-2/3 min-h-screen p-4">
|
||||
|
@ -41,7 +45,7 @@ export default function Home() {
|
|||
{/* TODO(hayk): Convert into components. */}
|
||||
|
||||
<Settings />
|
||||
<Pause />
|
||||
<Pause paused={paused} setPaused={setPaused} />
|
||||
|
||||
<input
|
||||
className="fixed z-90 bottom-20 right-40 w-1/2 h-12 pl-3 text-xl text-black"
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 75 KiB |
Loading…
Reference in New Issue