231 lines
5.8 KiB
TypeScript
231 lines
5.8 KiB
TypeScript
import { METADATA, NAVIGATION, UI } from '@/constants';
|
|
import React, {
|
|
ReactElement,
|
|
useCallback,
|
|
useContext,
|
|
useEffect,
|
|
useState,
|
|
} from 'react';
|
|
|
|
import CustomHead from '@/components/CustomHead';
|
|
import { ReactComponent as LoadingSVG } from '@/assets/svgs/loader.svg';
|
|
import { ScreenContext } from '@/contexts/screen';
|
|
import { SideMenuItem } from '@/state/navigation';
|
|
import classNames from 'classnames';
|
|
import panzoom from 'panzoom';
|
|
|
|
let pz = null; // global panzoom instance
|
|
|
|
type RoadmapCanvasProps = {
|
|
loaded: boolean;
|
|
canScaleMore: boolean;
|
|
showExplanation: boolean;
|
|
setShowExplanation: any;
|
|
isMobile: boolean;
|
|
};
|
|
|
|
const RoadmapCanvas = (props: RoadmapCanvasProps): ReactElement => {
|
|
const {
|
|
loaded,
|
|
canScaleMore,
|
|
showExplanation,
|
|
setShowExplanation,
|
|
isMobile,
|
|
} = props;
|
|
|
|
return (
|
|
<div
|
|
className={classNames(
|
|
'relative',
|
|
loaded ? 'visibility' : 'invisible',
|
|
isMobile && showExplanation && 'bg-tertiary',
|
|
)}
|
|
style={{
|
|
height: loaded ? `calc(100vh - ${UI.HEADER_HEIGHT_PX}px)` : '0vh',
|
|
}}
|
|
>
|
|
{!(isMobile && showExplanation) && (
|
|
<canvas
|
|
id={'#roadmap-image'}
|
|
aria-label={"Oxen's roadmap for the future shown as a progress tree"}
|
|
className={classNames('cursor-move z-0')}
|
|
// upscaled for better text rendering
|
|
// mobile and tablets have smaller upscale limit
|
|
width={3686 * (canScaleMore ? 1.75 : 1.45)}
|
|
height={2073 * (canScaleMore ? 1.75 : 1.45)}
|
|
/>
|
|
)}
|
|
{loaded && showExplanation && (
|
|
<div
|
|
className={classNames(
|
|
'relative flex justify-center items-center cursor-pointer',
|
|
'tablet:absolute tablet:block tablet:left-6 tablet:bottom-6',
|
|
)}
|
|
style={{
|
|
height: isMobile && showExplanation ? '100%' : 304.8,
|
|
width: isMobile && showExplanation ? '100%' : 313.6,
|
|
}}
|
|
onClick={() => {
|
|
setShowExplanation(false);
|
|
}}
|
|
>
|
|
{/* eslint-disable @next/next/no-img-element */}
|
|
<img
|
|
src={'/svgs/roadmap-explanation.svg'}
|
|
alt="Oxen Roadmap Explanation"
|
|
height={isMobile && showExplanation ? '100%' : 762 / 2.5}
|
|
width={isMobile && showExplanation ? '100%' : 784 / 2.5}
|
|
/>
|
|
</div>
|
|
)}
|
|
{loaded && !(isMobile && showExplanation) && (
|
|
<>
|
|
<div className={classNames('z-10 absolute right-6 bottom-6')}>
|
|
{/* eslint-disable @next/next/no-img-element */}
|
|
<img
|
|
src={'/svgs/roadmap-key.svg'}
|
|
alt="Oxen Roadmap Legend"
|
|
height={isMobile ? 180 : 242}
|
|
width={isMobile ? 150 : 200}
|
|
/>
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default function Roadmap() {
|
|
const { isMobile, isTablet, isHuge, isEnormous } = useContext(ScreenContext);
|
|
const [loaded, setLoaded] = useState(false);
|
|
const [showExplanation, setShowExplanation] = useState(true);
|
|
|
|
const startup = useCallback(() => {
|
|
if (isMobile && showExplanation) {
|
|
console.log('mobile popup loaded');
|
|
setLoaded(true);
|
|
return;
|
|
}
|
|
|
|
const canvasHolder = document.getElementById(
|
|
'#roadmap-image',
|
|
) as HTMLCanvasElement;
|
|
const context = canvasHolder.getContext('2d');
|
|
const backgroundImage = new Image();
|
|
backgroundImage.src = '/svgs/roadmap.svg';
|
|
|
|
backgroundImage.onload = function () {
|
|
context.drawImage(
|
|
backgroundImage,
|
|
0,
|
|
0,
|
|
canvasHolder.width,
|
|
canvasHolder.height,
|
|
);
|
|
context.save();
|
|
|
|
console.log('roadmap loaded');
|
|
setLoaded(true);
|
|
};
|
|
}, [isMobile, showExplanation]);
|
|
|
|
useEffect(() => {
|
|
startup();
|
|
|
|
if (loaded) {
|
|
if (isMobile && showExplanation || (!isMobile && !showExplanation)) {
|
|
return;
|
|
}
|
|
|
|
const roadmapEl = document.getElementById('#roadmap-image');
|
|
pz = panzoom(roadmapEl, {
|
|
initialZoom: isMobile
|
|
? 0.3
|
|
: isTablet
|
|
? 0.4
|
|
: isHuge
|
|
? 0.3333
|
|
: isEnormous
|
|
? 0.6
|
|
: 0.25,
|
|
minZoom: isMobile
|
|
? 0.07
|
|
: isTablet
|
|
? 0.125
|
|
: isHuge
|
|
? 0.12
|
|
: isEnormous
|
|
? 0.2
|
|
: 0.1,
|
|
autocenter: false,
|
|
initialX: isMobile
|
|
? -900
|
|
: isTablet
|
|
? -1200
|
|
: isHuge
|
|
? -800
|
|
: isEnormous
|
|
? -2200
|
|
: -600,
|
|
initialY: isMobile
|
|
? -100
|
|
: isTablet
|
|
? -200
|
|
: isHuge
|
|
? -100
|
|
: isEnormous
|
|
? -300
|
|
: -100,
|
|
bounds: true,
|
|
boundsPadding: isMobile ? 0 : isTablet ? 0 : -0.1,
|
|
});
|
|
}
|
|
|
|
() => {
|
|
if (loaded && pz) {
|
|
pz.dispose();
|
|
}
|
|
};
|
|
}, [
|
|
isMobile,
|
|
isTablet,
|
|
isHuge,
|
|
isEnormous,
|
|
loaded,
|
|
startup,
|
|
showExplanation,
|
|
]);
|
|
|
|
return (
|
|
<>
|
|
<CustomHead
|
|
title={NAVIGATION.SIDE_MENU_ITEMS[SideMenuItem.ROADMAP].label}
|
|
metadata={METADATA.ROADMAP_PAGE}
|
|
/>
|
|
{!loaded && (
|
|
<div
|
|
className={classNames('flex justify-center items-center w-100')}
|
|
title="loading"
|
|
style={{
|
|
height: `calc(100vh - ${UI.HEADER_HEIGHT_PX}px)`,
|
|
}}
|
|
>
|
|
<LoadingSVG
|
|
className={classNames(
|
|
'w-48 h-48 mx-auto text-primary fill-current -mt-8',
|
|
'tablet:-mt-32',
|
|
)}
|
|
/>
|
|
</div>
|
|
)}
|
|
<RoadmapCanvas
|
|
loaded={loaded}
|
|
canScaleMore={!isMobile && !isTablet}
|
|
showExplanation={showExplanation}
|
|
setShowExplanation={setShowExplanation}
|
|
isMobile={isMobile}
|
|
/>
|
|
</>
|
|
);
|
|
}
|