animation changes
This commit is contained in:
parent
c17c233ba4
commit
5abc04c382
@ -2,25 +2,36 @@ import type React from "react"
|
|||||||
import type { Metadata } from "next"
|
import type { Metadata } from "next"
|
||||||
import { Analytics } from "@vercel/analytics/next"
|
import { Analytics } from "@vercel/analytics/next"
|
||||||
import "./globals.css"
|
import "./globals.css"
|
||||||
|
import LadderClimb from "@/components/ladderclimber"
|
||||||
|
import Navbar from "@/components/navbar"
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "School For Schools",
|
title: "School For Schools",
|
||||||
description: "Combining expertise in education with cutting-edge technology",
|
description: "Combining expertise in education with cutting-edge technology",
|
||||||
generator: "v0.app",
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||||
children,
|
|
||||||
}: Readonly<{
|
|
||||||
children: React.ReactNode
|
|
||||||
}>) {
|
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<body className="font-sans antialiased" style={{ fontFamily: "DIN Alternate, sans-serif" }} suppressHydrationWarning>
|
<body
|
||||||
|
className="font-sans antialiased scrollbar-hide"
|
||||||
|
style={{ fontFamily: "DIN Alternate, sans-serif", scrollbarWidth: "none", msOverflowStyle: "none" }}
|
||||||
|
>
|
||||||
|
<style>{`
|
||||||
|
html::-webkit-scrollbar,
|
||||||
|
body::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
<Navbar />
|
||||||
|
|
||||||
|
{/* LadderClimb is now global */}
|
||||||
|
<LadderClimb />
|
||||||
|
|
||||||
|
{/* All page content */}
|
||||||
{children}
|
{children}
|
||||||
<Analytics />
|
<Analytics />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
20
app/page.tsx
20
app/page.tsx
@ -5,17 +5,19 @@ import Testimonials from "@/components/testimonials"
|
|||||||
import OurOfferings from "@/components/our-offerings"
|
import OurOfferings from "@/components/our-offerings"
|
||||||
import TrustedBy from "@/components/trusted-by"
|
import TrustedBy from "@/components/trusted-by"
|
||||||
import Footer from "@/components/footer"
|
import Footer from "@/components/footer"
|
||||||
|
import LadderClimb from "@/components/ladderclimber"
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
<main className="w-full">
|
<>
|
||||||
<Navbar />
|
<main className="w-full">
|
||||||
<MainHero />
|
<MainHero />
|
||||||
<HeroSection /> {/* This is the 'Why SFS' section */}
|
<HeroSection /> {/* This is the 'Why SFS' section */}
|
||||||
<OurOfferings />
|
<OurOfferings />
|
||||||
<Testimonials />
|
<Testimonials />
|
||||||
<TrustedBy />
|
<TrustedBy />
|
||||||
<Footer />
|
<Footer />
|
||||||
</main>
|
</main>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
143
components/ladderclimber.tsx
Normal file
143
components/ladderclimber.tsx
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import React, { useEffect, useRef, useState } from "react"
|
||||||
|
|
||||||
|
export default function LadderClimb() {
|
||||||
|
const charRef = useRef<HTMLDivElement>(null)
|
||||||
|
const ladderRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
|
const [animation, setAnimation] = useState<"idle" | "climbing">("idle")
|
||||||
|
const [visible, setVisible] = useState(true)
|
||||||
|
|
||||||
|
const ladderHeight = useRef(0)
|
||||||
|
const scrollTimeout = useRef<any>(null)
|
||||||
|
|
||||||
|
const updateDimensions = () => {
|
||||||
|
if (ladderRef.current) {
|
||||||
|
ladderHeight.current = ladderRef.current.clientHeight
|
||||||
|
}
|
||||||
|
if (charRef.current) {
|
||||||
|
charRef.current.style.transform = `translateY(0px)`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
updateDimensions()
|
||||||
|
setAnimation("idle")
|
||||||
|
|
||||||
|
window.addEventListener("resize", updateDimensions)
|
||||||
|
|
||||||
|
const handleScroll = () => {
|
||||||
|
if (!charRef.current || !ladderRef.current) return
|
||||||
|
|
||||||
|
// show ladder & climbing animation
|
||||||
|
setVisible(true)
|
||||||
|
setAnimation("climbing")
|
||||||
|
|
||||||
|
const scrollTop = window.scrollY
|
||||||
|
const docHeight = document.body.scrollHeight
|
||||||
|
const viewportHeight = window.innerHeight
|
||||||
|
|
||||||
|
let progress = scrollTop / (docHeight - viewportHeight)
|
||||||
|
progress = Math.max(0, Math.min(1, progress))
|
||||||
|
|
||||||
|
const topOffset = 174
|
||||||
|
const bottomOffset = 30
|
||||||
|
const maxClimb = ladderHeight.current - topOffset - bottomOffset
|
||||||
|
|
||||||
|
const y = progress * maxClimb
|
||||||
|
charRef.current.style.transform = `translateY(-${y}px)`
|
||||||
|
|
||||||
|
// hide smoothly after scroll stops
|
||||||
|
if (scrollTimeout.current) clearTimeout(scrollTimeout.current)
|
||||||
|
scrollTimeout.current = setTimeout(() => {
|
||||||
|
setAnimation("idle")
|
||||||
|
setVisible(false)
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("scroll", handleScroll)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("scroll", handleScroll)
|
||||||
|
window.removeEventListener("resize", updateDimensions)
|
||||||
|
if (scrollTimeout.current) clearTimeout(scrollTimeout.current)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Ladder container */}
|
||||||
|
<div
|
||||||
|
ref={ladderRef}
|
||||||
|
style={{
|
||||||
|
position: "fixed",
|
||||||
|
right: 0,
|
||||||
|
top: 80,
|
||||||
|
height: "100vh",
|
||||||
|
width: "100px",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "flex-end",
|
||||||
|
zIndex: 999,
|
||||||
|
|
||||||
|
// smooth hide / show
|
||||||
|
opacity: visible ? 1 : 0,
|
||||||
|
transform: visible ? "translateX(0)" : "translateX(40px)",
|
||||||
|
pointerEvents: visible ? "auto" : "none",
|
||||||
|
transition: "opacity 0.8s ease, transform 0.8s ease"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Ladder background */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: "100%",
|
||||||
|
width: "40px",
|
||||||
|
background:
|
||||||
|
"repeating-linear-gradient(to bottom, #666 0, #666 8px, transparent 8px, transparent 30px)",
|
||||||
|
borderLeft: "8px solid #666",
|
||||||
|
borderRight: "8px solid #666",
|
||||||
|
zIndex: 1
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Character */}
|
||||||
|
<div
|
||||||
|
ref={charRef}
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
bottom: 45,
|
||||||
|
left: "50%",
|
||||||
|
marginLeft: "-100px",
|
||||||
|
width: "200px",
|
||||||
|
zIndex: 10,
|
||||||
|
willChange: "transform",
|
||||||
|
transition: "transform 0.15s linear"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* CLIMBING */}
|
||||||
|
{animation === "climbing" && (
|
||||||
|
<img
|
||||||
|
src="./climber21.png"
|
||||||
|
alt="Climbing"
|
||||||
|
style={{ width: "400px", height: "200px" }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* IDLE */}
|
||||||
|
{animation === "idle" && (
|
||||||
|
<img
|
||||||
|
src="./Idle3.png"
|
||||||
|
alt="Idle"
|
||||||
|
style={{
|
||||||
|
marginLeft: "10px",
|
||||||
|
width: "400px",
|
||||||
|
height: "200px"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -75,7 +75,7 @@ export default function Navbar() {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className="w-full bg-white border-b border-gray-200">
|
<nav className="fixed top-0 left-0 right-0 z-50 w-full bg-white border-b border-gray-200">
|
||||||
<div className="w-full pl-6 sm:pl-8 lg:pl-12 pr-4 sm:pr-6 lg:pr-8">
|
<div className="w-full pl-6 sm:pl-8 lg:pl-12 pr-4 sm:pr-6 lg:pr-8">
|
||||||
<div className="flex justify-between items-center h-20">
|
<div className="flex justify-between items-center h-20">
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
|
|||||||
BIN
public/Idle1.png
Normal file
BIN
public/Idle1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 77 KiB |
BIN
public/Idle3.png
Normal file
BIN
public/Idle3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
BIN
public/climber1-removebg.png
Normal file
BIN
public/climber1-removebg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
BIN
public/climber2.png
Normal file
BIN
public/climber2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 76 KiB |
BIN
public/climber21.png
Normal file
BIN
public/climber21.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
BIN
public/ladder.png
Normal file
BIN
public/ladder.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
Loading…
Reference in New Issue
Block a user