Skip to content

Commit

Permalink
added globe in about
Browse files Browse the repository at this point in the history
suvanbanerjee committed Aug 1, 2024
1 parent 3356d28 commit cbddc2d
Showing 4 changed files with 8,401 additions and 1,052 deletions.
2 changes: 2 additions & 0 deletions components/about.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Link from 'next/link'
import Globe from './magicui/globe'

export default function About() {
return (
@@ -9,6 +10,7 @@ export default function About() {
{/* Section header */}
<div className="max-w-6xl mx-auto text-center pb-12 md:pb-16">
<h2 className="h2 mb-4 dark:text-gray-300">About Open Voice OS</h2>
<Globe className='mx-auto relative w-64 h-64' />
<p className="text-xl text-gray-600 dark:text-gray-400 pb-5" data-aos="zoom-y-out">Meet OpenVoiceOS, a newcomer in the smart speaker scene, offering a different choice from the usual options like Amazon Echo and Google Home. With OpenVoiceOS, you have control over your data and can customize your smart speaker experience. It's designed to respond accurately to your commands, whether you speak or touch the screen. OpenVoiceOS is open-source, meaning anyone can help improve it, and it can run offline for added privacy. If you're looking for a smart speaker that puts you in control, OpenVoiceOS might be the one for you.</p>
<p className=" bg-gray-200 dark:bg-gray-800 p-4 rounded-3xl text-center text-gray-900 dark:text-gray-200 w-fit mx-auto">
Open Voice OS is a part of a larger ecosystem of FOSS voice technologies. Check <Link href="/friends" className="text-blue-600 dark:text-blue-400 font-bold">Friends Projects</Link> to learn more.
129 changes: 129 additions & 0 deletions components/magicui/globe.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
"use client";

import { useCallback, useEffect, useRef } from "react";
import createGlobe, { COBEOptions } from "cobe";
import { useSpring } from "react-spring";

import { cn } from "@/lib/utils";

const GLOBE_CONFIG: COBEOptions = {
width: 800,
height: 800,
onRender: () => {},
devicePixelRatio: 2,
phi: 0,
theta: 0.3,
dark: 0,
diffuse: 0.4,
mapSamples: 16000,
mapBrightness: 1.2,
baseColor: [1, 1, 1],
markerColor: [251 / 255, 100 / 255, 21 / 255],
glowColor: [1, 1, 1],
markers: [
{ location: [14.5995, 120.9842], size: 0.03 },
{ location: [19.076, 72.8777], size: 0.1 },
{ location: [23.8103, 90.4125], size: 0.05 },
{ location: [30.0444, 31.2357], size: 0.07 },
{ location: [39.9042, 116.4074], size: 0.08 },
{ location: [-23.5505, -46.6333], size: 0.1 },
{ location: [19.4326, -99.1332], size: 0.1 },
{ location: [40.7128, -74.006], size: 0.1 },
{ location: [34.6937, 135.5022], size: 0.05 },
{ location: [41.0082, 28.9784], size: 0.06 },
],
};

export default function Globe({
className,
config = GLOBE_CONFIG,
}: {
className?: string;
config?: COBEOptions;
}) {
let phi = 0;
let width = 0;
const canvasRef = useRef<HTMLCanvasElement>(null);
const pointerInteracting = useRef(null);
const pointerInteractionMovement = useRef(0);
const [{ r }, api] = useSpring(() => ({
r: 0,
config: {
mass: 1,
tension: 280,
friction: 40,
precision: 0.001,
},
}));

const updatePointerInteraction = (value: any) => {
pointerInteracting.current = value;
canvasRef.current!.style.cursor = value ? "grabbing" : "grab";
};

const updateMovement = (clientX: any) => {
if (pointerInteracting.current !== null) {
const delta = clientX - pointerInteracting.current;
pointerInteractionMovement.current = delta;
api.start({ r: delta / 200 });
}
};

const onRender = useCallback(
(state: Record<string, any>) => {
if (!pointerInteracting.current) phi += 0.005;
state.phi = phi + r.get();
state.width = width * 2;
state.height = width * 2;
},
[pointerInteracting, phi, r],
);

const onResize = () => {
if (canvasRef.current) {
width = canvasRef.current.offsetWidth;
}
};

useEffect(() => {
window.addEventListener("resize", onResize);
onResize();

const globe = createGlobe(canvasRef.current!, {
...config,
width: width * 2,
height: width * 2,
onRender,
});

setTimeout(() => (canvasRef.current!.style.opacity = "1"));
return () => globe.destroy();
}, []);

return (
<div
className={cn(
"absolute inset-0 mx-auto aspect-[1/1] w-full max-w-[600px]",
className,
)}
>
<canvas
className={cn(
"h-full w-full opacity-0 transition-opacity duration-500 [contain:layout_paint_size]",
)}
ref={canvasRef}
onPointerDown={(e) =>
updatePointerInteraction(
e.clientX - pointerInteractionMovement.current,
)
}
onPointerUp={() => updatePointerInteraction(null)}
onPointerOut={() => updatePointerInteraction(null)}
onMouseMove={(e) => updateMovement(e.clientX)}
onTouchMove={(e) =>
e.touches[0] && updateMovement(e.touches[0].clientX)
}
/>
</div>
);
}
9,320 changes: 8,268 additions & 1,052 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -20,12 +20,14 @@
"canvas-confetti": "^1.9.3",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cobe": "^0.6.3",
"framer-motion": "^11.3.21",
"lucide-react": "^0.419.0",
"next": "^14.0.4",
"next-themes": "^0.3.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-spring": "^9.7.4",
"tailwind-merge": "^2.4.0",
"tailwindcss-animate": "^1.0.7",
"typescript": "^5.3.3"

0 comments on commit cbddc2d

Please sign in to comment.