Skip to content

Commit

Permalink
refactor intro images
Browse files Browse the repository at this point in the history
  • Loading branch information
SheepTester committed Nov 25, 2024
1 parent 0e0a00e commit 261d752
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 89 deletions.
184 changes: 97 additions & 87 deletions src/components/onboarding/Intro/index.tsx
Original file line number Diff line number Diff line change
@@ -1,84 +1,126 @@
import Allocation from '@/public/assets/graphics/onboarding/ACM_Fall23Allocation-JustinLu.jpg';
import HoldBoba from '@/public/assets/graphics/onboarding/ACM_Fall24BitByteInfo_1-JustinLu.jpg';
import Murou from '@/public/assets/graphics/onboarding/ACM_Fall24BitByteInfo_2-JustinLu.jpg';
import Bonfire from '@/public/assets/graphics/onboarding/ACM_Fall24Bonfire_1-JustinLu.jpg';
import RaymondBack from '@/public/assets/graphics/onboarding/ACM_Fall24Bonfire_2-JustinLu.jpg';
import TiltKickoff from '@/public/assets/graphics/onboarding/ACM_Fall24Kickoff_1-JustinLu.jpg';
import FocusPerson from '@/public/assets/graphics/onboarding/ACM_Fall24Kickoff_2-JustinLu.jpg';
import KickoffBig from '@/public/assets/graphics/onboarding/ACM_Fall24Kickoff_3-JustinLu.jpg';
import BitByteAllocation from '@/public/assets/graphics/onboarding/Fall23Allocation-JustinLu.jpg';
import BitByteInfoSession from '@/public/assets/graphics/onboarding/Fall24BitByteInfo_1-JustinLu.jpg';
import BitByteSpeedFriending from '@/public/assets/graphics/onboarding/Fall24BitByteInfo_2-JustinLu.jpg';
import BonfireMarshmellows from '@/public/assets/graphics/onboarding/Fall24Bonfire_1-JustinLu.jpg';
import BonfireBeach from '@/public/assets/graphics/onboarding/Fall24Bonfire_2-JustinLu.jpg';
import KickoffSideView from '@/public/assets/graphics/onboarding/Fall24Kickoff_1-JustinLu.jpg';
import KickoffCloseUp from '@/public/assets/graphics/onboarding/Fall24Kickoff_2-JustinLu.jpg';
import KickoffFrontView from '@/public/assets/graphics/onboarding/Fall24Kickoff_3-JustinLu.jpg';
import Image, { StaticImageData } from 'next/image';
import { useEffect, useRef, useState } from 'react';
import styles from './style.module.scss';

type ImageBounds = {
x: number;
y: number;
width: number;
height: number;
};

function getCenter({ x, y, width, height }: ImageBounds): { x: number; y: number } {
return { x: x + width / 2, y: y + height / 2 };
}

type IntroImage = {
src: StaticImageData;
alt: string;
desktopSize: [x: number, y: number, width: number, height: number];
mobileSize: [x: number, y: number, width: number, height: number];
desktopSize: ImageBounds;
mobileSize: ImageBounds;
round?: boolean;
};

// https://www.figma.com/design/GiWZdbzJ2uxyknpCrB9UK6/acm-onboarding
// Measurements from
// https://www.figma.com/design/GiWZdbzJ2uxyknpCrB9UK6/acm-onboarding, ordered
// from bottom to top (reversed from Figma, where layers are ordered top to
// bottom)
const firstImage = {
src: KickoffFrontView,
alt: 'A large audience of students forming diamonds with their hands',
desktopSize: { x: 173, y: 116, width: 631, height: 308 },
mobileSize: { x: 12, y: 173, width: 287, height: 206 },
round: true,
};
const images: IntroImage[] = [
firstImage,
{
src: FocusPerson,
alt: 'A student smiling in a crowd',
desktopSize: [89, 46, 168, 168],
mobileSize: [24, 326, 109, 109],
round: true,
src: BonfireBeach,
alt: 'Students standing on a beach on a cloudy day',
desktopSize: { x: 289, y: 29, width: 326, height: 146 },
mobileSize: { x: 0, y: 116, width: 146, height: 110 },
},
{
src: Bonfire,
alt: 'Students around a bonfire holding marshmellows on skewers',
desktopSize: [740, 285, 208, 208],
mobileSize: [158, 86, 153, 153],
round: true,
src: BitByteAllocation,
alt: 'A group photo of students standing before Geisel and Snake Path',
desktopSize: { x: 57, y: 357, width: 299, height: 135 },
mobileSize: { x: 0, y: 422, width: 270, height: 131 },
},
{
src: Murou,
alt: 'Students chatting',
desktopSize: [49, 175, 138, 138],
mobileSize: [213, 293, 86, 86],
src: KickoffSideView,
alt: 'A large audience of students at ACM Kickoff',
desktopSize: { x: 327, y: 390, width: 393, height: 134 },
mobileSize: { x: 0, y: 0, width: 252, height: 108 },
round: true,
},
{
src: HoldBoba,
src: BitByteInfoSession,
alt: 'An audience of students watching a presentation',
desktopSize: [685, 72, 233, 135],
mobileSize: [124, 369, 187, 84],
desktopSize: { x: 685, y: 72, width: 233, height: 135 },
mobileSize: { x: 124, y: 369, width: 187, height: 84 },
},
{
src: TiltKickoff,
alt: 'A large audience of students at ACM Kickoff',
desktopSize: [327, 390, 393, 134],
mobileSize: [0, 0, 252, 108],
src: BitByteSpeedFriending,
alt: 'Students chatting',
desktopSize: { x: 49, y: 175, width: 138, height: 138 },
mobileSize: { x: 213, y: 293, width: 86, height: 86 },
round: true,
},
{
src: Allocation,
alt: 'A group photo of students standing before Geisel and Snake Path',
desktopSize: [57, 357, 299, 135],
mobileSize: [0, 422, 270, 131],
},
{
src: RaymondBack,
alt: 'Students standing on a beach on a cloudy day',
desktopSize: [289, 29, 326, 146],
mobileSize: [0, 116, 146, 110],
src: BonfireMarshmellows,
alt: 'Students around a bonfire holding marshmellows on skewers',
desktopSize: { x: 740, y: 285, width: 208, height: 208 },
mobileSize: { x: 158, y: 86, width: 153, height: 153 },
round: true,
},
{
src: KickoffBig,
alt: 'A large audience of students forming diamonds with their hands',
desktopSize: [173, 116, 631, 308],
mobileSize: [12, 173, 287, 206],
src: KickoffCloseUp,
alt: 'A student smiling in a crowd',
desktopSize: { x: 89, y: 46, width: 168, height: 168 },
mobileSize: { x: 24, y: 326, width: 109, height: 109 },
round: true,
},
];
images.reverse();
const DESKTOP_OFFSET_X = 173 + 631 / 2;
const DESKTOP_OFFSET_Y = 116 + 308 / 2;
const MOBILE_OFFSET_X = 25 + 261 / 2;
const MOBILE_OFFSET_Y = 203 + 146 / 2;
// The center of the coordinate system
const DESKTOP_OFFSET = getCenter(firstImage.desktopSize);
const MOBILE_OFFSET = getCenter(firstImage.mobileSize);

const displayImage = (
mode: 'desktop' | 'mobile',
{ src, alt, round, ...sizes }: IntroImage,
index: number
) => {
const { x, y, width, height } = sizes[`${mode}Size`];
const offset = mode === 'desktop' ? DESKTOP_OFFSET : MOBILE_OFFSET;
return (
<Image
className={`${styles.image} ${round ? styles.pill : ''} ${styles[`${mode}Only`]}`}
src={src}
alt={alt}
width={width}
height={height}
style={{
left:
mode === 'desktop'
? `${x - offset.x}px`
: // Widen the mobile image layout as the screen gets wider
`calc(${x - offset.x}px + ${(x - offset.x + width / 2) * 0.2}vw)`,
top: `${y - offset.y}px`,
transformOrigin: `${offset.x - x}px ${offset.y - y}px`,
animationDelay: `${index * 0.1 + 0.5}s`,
animationDuration: `${index * 0.05 + 1}s`,
}}
/>
);
};

const Intro = () => {
const [mouseX, setMouseX] = useState(0);
Expand All @@ -103,50 +145,18 @@ const Intro = () => {
return (
<div className={styles.wrapper}>
<div className={styles.anchor} ref={ref}>
{images.map(({ src, alt, desktopSize, mobileSize, round }, i) => (
{images.map((image, i) => (
<div
key={src.src}
key={image.src.src}
className={styles.imageWrapper}
style={{
transform: `translate(${mouseX / (10 + images.length - i)}px, ${
mouseY / (10 + images.length - i)
}px)`,
}}
>
<Image
className={`${styles.image} ${round ? styles.pill : ''} ${styles.desktopOnly}`}
src={src}
alt={alt}
width={desktopSize[2]}
height={desktopSize[3]}
style={{
left: `${desktopSize[0] - DESKTOP_OFFSET_X}px`,
top: `${desktopSize[1] - DESKTOP_OFFSET_Y}px`,
transformOrigin: `${DESKTOP_OFFSET_X - desktopSize[0]}px ${
DESKTOP_OFFSET_Y - desktopSize[1]
}px`,
animationDelay: `${i * 0.1 + 0.5}s`,
animationDuration: `${i * 0.05 + 1}s`,
}}
/>
<Image
className={`${styles.image} ${round ? styles.pill : ''} ${styles.mobileOnly}`}
src={src}
alt={alt}
width={mobileSize[2]}
height={mobileSize[3]}
style={{
left: `calc(${mobileSize[0] - MOBILE_OFFSET_X}px + ${
(mobileSize[0] - MOBILE_OFFSET_X + mobileSize[2] / 2) * 0.2
}vw)`,
top: `${mobileSize[1] - MOBILE_OFFSET_Y}px`,
transformOrigin: `${MOBILE_OFFSET_X - mobileSize[0]}px ${
MOBILE_OFFSET_Y - mobileSize[1]
}px`,
animationDelay: `${i * 0.1 + 0.5}s`,
animationDuration: `${i * 0.05 + 1}s`,
}}
/>
{displayImage('desktop', image, i)}
{displayImage('mobile', image, i)}
</div>
))}
</div>
Expand Down
2 changes: 0 additions & 2 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ const PortalHomePage = ({
setCheckinModalVisible(false);

// Start onboarding after checking in
// TEMP: This should be saved server-side in the future
// Do not start onboarding if user already attended other events
if (user.onboardingSeen) {
return;
}
Expand Down

0 comments on commit 261d752

Please sign in to comment.