Spaces:
Running
Running
File size: 2,815 Bytes
dce7eca | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | "use client";
import React, { useEffect, useRef, useState } from 'react';
interface PanoramaViewerProps {
imageUrl: string;
className?: string;
}
declare global {
interface Window {
pannellum: any;
}
}
const PanoramaViewer: React.FC<PanoramaViewerProps> = ({ imageUrl, className }) => {
const viewerRef = useRef<HTMLDivElement>(null);
const pannellumInstance = useRef<any>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
// Check if pannellum is loaded
const initViewer = () => {
if (!window.pannellum) {
console.warn("Pannellum not loaded yet, retrying...");
setTimeout(initViewer, 500);
return;
}
if (viewerRef.current && imageUrl) {
// Destroy existing instance if it exists
if (pannellumInstance.current) {
try {
pannellumInstance.current.destroy();
} catch (e) {
console.warn("Error destroying pannellum instance:", e);
}
}
try {
// Initialize Pannellum
pannellumInstance.current = window.pannellum.viewer(viewerRef.current, {
type: 'equirectangular',
panorama: imageUrl,
autoLoad: true,
showControls: true,
compass: false, // Set to false by default for cleaner look
mouseZoom: true,
hfov: 100,
vaov: 180,
haov: 360,
crossOrigin: "anonymous"
});
setError(null);
} catch (err: any) {
console.error("Pannellum initialization error:", err);
setError(err.message);
}
}
};
initViewer();
return () => {
if (pannellumInstance.current) {
try {
pannellumInstance.current.destroy();
} catch (e) { }
}
};
}, [imageUrl]);
if (error) {
return (
<div className="w-full h-full flex items-center justify-center bg-slate-900 text-red-400 p-4 text-center">
<p>Error loading viewer: {error}<br />Image might be too large or inaccessible.</p>
</div>
);
}
return (
<div
ref={viewerRef}
className={`w-full h-full rounded-xl overflow-hidden shadow-2xl bg-black border border-slate-700 ${className || ''}`}
/>
);
};
export default PanoramaViewer;
|