forked from ourworld_web/www_engage_os
92 lines
2.1 KiB
TypeScript
92 lines
2.1 KiB
TypeScript
'use client';
|
|
import React, { useEffect, useRef, useState } from 'react';
|
|
import createGlobe from 'cobe';
|
|
import { cn } from '@/lib/utils';
|
|
interface EarthProps {
|
|
className?: string;
|
|
theta?: number;
|
|
dark?: number;
|
|
scale?: number;
|
|
diffuse?: number;
|
|
mapSamples?: number;
|
|
mapBrightness?: number;
|
|
baseColor?: [number, number, number];
|
|
markerColor?: [number, number, number];
|
|
glowColor?: [number, number, number];
|
|
}
|
|
const Earth: React.FC<EarthProps> = ({
|
|
className,
|
|
theta = 0.25,
|
|
dark = 1,
|
|
scale = 1.1,
|
|
diffuse = 1.2,
|
|
mapSamples = 40000,
|
|
mapBrightness = 6,
|
|
baseColor = [0.4, 0.6509, 1],
|
|
markerColor = [1, 0, 0],
|
|
glowColor = [0.2745, 0.5765, 0.898],
|
|
}) => {
|
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
|
|
useEffect(() => {
|
|
let width = 0;
|
|
const onResize = () =>
|
|
canvasRef.current && (width = canvasRef.current.offsetWidth);
|
|
window.addEventListener('resize', onResize);
|
|
onResize();
|
|
let phi = 0;
|
|
|
|
onResize();
|
|
const globe = createGlobe(canvasRef.current!, {
|
|
devicePixelRatio: 2,
|
|
width: width * 2,
|
|
height: width * 2,
|
|
phi: 0,
|
|
theta: theta,
|
|
dark: dark,
|
|
scale: scale,
|
|
diffuse: diffuse,
|
|
mapSamples: mapSamples,
|
|
mapBrightness: mapBrightness,
|
|
baseColor: baseColor,
|
|
markerColor: markerColor,
|
|
glowColor: glowColor,
|
|
opacity: 1,
|
|
offset: [0, 0],
|
|
markers: [
|
|
// longitude latitude
|
|
],
|
|
onRender: (state: Record<string, any>) => {
|
|
// Called on every animation frame.
|
|
// `state` will be an empty object, return updated params.\
|
|
state.phi = phi;
|
|
phi += 0.003;
|
|
},
|
|
});
|
|
|
|
return () => {
|
|
globe.destroy();
|
|
};
|
|
}, []);
|
|
|
|
return (
|
|
<div
|
|
className={cn(
|
|
'flex items-center justify-center z-[10] w-full max-w-[350px] mx-auto',
|
|
className
|
|
)}
|
|
>
|
|
<canvas
|
|
ref={canvasRef}
|
|
style={{
|
|
width: '100%',
|
|
height: '100%',
|
|
maxWidth: '100%',
|
|
aspectRatio: '1',
|
|
}}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Earth; |