diff --git a/public/config/experiences.ts b/public/config/experiences.ts new file mode 100644 index 0000000..72da058 --- /dev/null +++ b/public/config/experiences.ts @@ -0,0 +1,4 @@ +/** + * list of allowed ids. + */ +export const ALLOWED_IDS = ["demoModelViewer", "iceCore", "glacierInTime"]; diff --git a/src/app/demoModelViewer/modelViewer.module.css b/src/app/demoModelViewer/modelViewer.module.css new file mode 100644 index 0000000..e71c21d --- /dev/null +++ b/src/app/demoModelViewer/modelViewer.module.css @@ -0,0 +1,28 @@ +.mainContainer { + padding: 2rem; +} + +.instructionText { + margin-bottom: 1rem; +} + +.buttonWrapper { + margin-top: 20px; + margin-bottom: 20px; +} + +.backButton { + display: inline-block; + padding: 12px 24px; + background-color: #0070f3; + color: white; + text-decoration: none; + border-radius: 8px; + font-size: 16px; + font-weight: bold; + pointer-events: auto; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3); + transition: + background-color 0.2s ease, + transform 0.1s ease; +} diff --git a/src/app/demoModelViewer/page.tsx b/src/app/demoModelViewer/page.tsx index 8899978..3c407c6 100644 --- a/src/app/demoModelViewer/page.tsx +++ b/src/app/demoModelViewer/page.tsx @@ -1,28 +1,20 @@ import Link from "next/link"; +import { Manrope } from "next/font/google"; import ModelViewer from "../../components/ModelViewer"; +import styles from "./modelViewer.module.css"; + +const manrope = Manrope({ subsets: ["latin"] }); export default function Home() { return ( -
-

Interact with the object to rotate it

+
+

+ Interagisici con l`oggetto per ruotarlo +

-
- - ← Back to the scanner +
+ + ← Torna allo scanner
diff --git a/src/app/favicon.ico b/src/app/favicon.ico index 718d6fe..9bc9938 100644 Binary files a/src/app/favicon.ico and b/src/app/favicon.ico differ diff --git a/src/app/glacierInTime/glacierInTime.module.css b/src/app/glacierInTime/glacierInTime.module.css new file mode 100644 index 0000000..f52c148 --- /dev/null +++ b/src/app/glacierInTime/glacierInTime.module.css @@ -0,0 +1,130 @@ +.container { + position: relative; + width: 100vw; + height: 100dvh; + overflow: hidden; + background-color: #000; +} + +/* Invisible overlay to catch click*/ +.clickOverlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 8; + cursor: pointer; +} + +/* Marker image */ +.markerImage { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + max-width: 80vw; + max-height: 80vh; + width: auto; + height: auto; + transition: opacity 0.6s ease-in-out; + pointer-events: none; + z-index: 5; +} + +/* UI */ +.uiContainer { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + padding: 40px 20px; + z-index: 10; + pointer-events: none; + text-align: center; + box-sizing: border-box; +} + +/* Higher text group*/ +.textGroup { + display: flex; + flex-direction: column; + gap: 10px; +} + +.instructionText { + font-size: 1.2rem; + color: #fff; + text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.8); + margin: 0; +} + +.pulseText { + font-size: 1.5rem; + color: #fff; + font-weight: bold; + animation: pulse 2s infinite; + text-transform: uppercase; + letter-spacing: 1px; + text-shadow: 2px 2px 6px rgba(0, 0, 0, 0.9); + pointer-events: none; +} + +/* Lower button group*/ +.bottomGroup { + display: flex; + flex-direction: column; + align-items: center; + gap: 20px; + margin-bottom: 20px; +} + +.backButton { + pointer-events: auto; + display: inline-block; + padding: 12px 24px; + background-color: #0070f3; + color: white; + text-decoration: none; + border-radius: 8px; + font-size: 16px; + font-weight: bold; + opacity: 0.8; + transition: opacity 0.2s ease; +} + +.backButton:hover { + opacity: 1; +} + +/* Iframe AR */ +.iframeStyle { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border: none; + z-index: 1; +} + +/* Animation */ +@keyframes pulse { + 0% { + transform: scale(1); + opacity: 0.8; + } + 50% { + transform: scale(1.05); + opacity: 1; + } + 100% { + transform: scale(1); + opacity: 0.8; + } +} diff --git a/src/app/glacierInTime/page.tsx b/src/app/glacierInTime/page.tsx index 821e03c..b663f2a 100644 --- a/src/app/glacierInTime/page.tsx +++ b/src/app/glacierInTime/page.tsx @@ -10,10 +10,42 @@ import { getAdjustedARConfig, useIframeMessage, } from "@/utils/arHelper"; +import { BASE_PATH } from "@/utils/configHelper"; + +import styles from "./glacierInTime.module.css"; -// Inizializza il font +// Font initialization const manrope = Manrope({ subsets: ["latin"] }); -import { BASE_PATH } from "@/utils/configHelper"; + +// Reveal animation +const revealAnimation: CustomAnimation = { + name: "reveal", + config: { + type: "clip-z", + duration: 6000, + min: -1500, + max: 0, + }, +}; + +const baseConfig: ARConfig = { + markerType: "nft", + markerUrl: `${BASE_PATH}/nft/glacier-in-time/glacier-in-time-target`, + modelUrl: `${BASE_PATH}/models/glacier-in-time/Wrapper.gltf`, + scale: [250, 250, 250], + rotation: [0, 180, 0], + position: [125, 0, -180], + enableInteraction: false, + customAnimation: revealAnimation, +}; + +const IOS_OFFSETS: AROffsets = { + x: -40, + y: 0, + z: 0, +}; + +const markerImageUrl = `${BASE_PATH}/models/glacier-in-time/Marker.jpg`; export default function GlacierInTimePage() { const iframeRef = useRef(null); @@ -22,34 +54,6 @@ export default function GlacierInTimePage() { const [isMarkerFound, setIsMarkerFound] = useState(false); const [animationStarted, setAnimationStarted] = useState(false); - // Reveal animation - const revealAnimation: CustomAnimation = { - name: "reveal", - config: { - type: "clip-z", - duration: 6000, - min: -1500, - max: 0, - }, - }; - - const baseConfig: ARConfig = { - markerType: "nft", - markerUrl: `${BASE_PATH}/nft/glacier-in-time/glacier-in-time-target`, - modelUrl: `${BASE_PATH}/models/glacier-in-time/Wrapper.gltf`, - scale: [250, 250, 250], - rotation: [0, 180, 0], - position: [125, 0, -180], - enableInteraction: false, - customAnimation: revealAnimation, - }; - - const IOS_OFFSETS: AROffsets = { - x: -40, - y: 0, - z: 0, - }; - const config = getAdjustedARConfig(baseConfig, IOS_OFFSETS); let iframeSrc = `${BASE_PATH}/nft-ar.html?${buildARQueryString(config)}`; @@ -57,8 +61,6 @@ export default function GlacierInTimePage() { iframeSrc += `&debug=1`; } - const markerImageUrl = `${BASE_PATH}/models/glacier-in-time/Marker.jpg`; - // Listen for events from iframe useIframeMessage({ setIsMarkerFound, @@ -87,30 +89,10 @@ export default function GlacierInTimePage() { }; return ( -
+
{/* Invisible overlay to capture the click*/} {isMarkerFound && !animationStarted && ( -
+
)} {/* Overlay image */} @@ -119,99 +101,28 @@ export default function GlacierInTimePage() { alt="Inquadra questa immagine" width={512} height={1024} - style={{ - position: "absolute", - top: "50%", - left: "50%", - transform: "translate(-50%, -50%)", - maxWidth: "80vw", - maxHeight: "80vh", - width: "auto", - height: "auto", - opacity: isMarkerFound ? 0 : 0.4, - transition: "opacity 0.6s ease-in-out", - pointerEvents: "none", - zIndex: 5, - }} + className={styles.markerImage} + style={{ opacity: isMarkerFound ? 0 : 0.4 }} priority /> -
-
+
+
{!isMarkerFound && ( -

- Frame the image to start +

+ Inquadra l`immagine per iniziare

)} {isMarkerFound && !animationStarted && ( -
- Tocca per iniziare -
+
Tocca per iniziare
)}
{/* Go back button */} -
- - ← Back to the scanner +
+ + ← Torna allo scanner
@@ -219,36 +130,10 @@ export default function GlacierInTimePage() {