omniview-360
v1.0.0
Published
A powerful React Native package for creating immersive 360° panoramic viewing experiences. Render equirectangular images as interactive spheres with gesture and gyroscope support.
Maintainers
Readme
OmniView 360
A powerful React Native package for creating immersive 360° panoramic viewing experiences. Render equirectangular images as interactive spheres with gesture and gyroscope support—all processed locally on device.
✨ Features
- 🔄 360° Panoramic Rendering – Display equirectangular images in immersive spherical environments
- 👆 Touch Gestures – Swipe and drag to look around intuitively
- 📱 Gyroscope Support – Optional device motion tracking for hands-free navigation
- 🎯 Interactive Hotspots – Define and trigger actions on specific panoramic points
- 🚀 High Performance – Optimized Three.js rendering on native hardware
- 🔒 Privacy-First – All processing happens on-device; no cloud services needed
- 📦 Zero Dependency – Works standalone with React Native projects
🎯 Use Cases
| Use Case | Description | |----------|-------------| | 🏠 Real Estate | Virtual apartment tours, property walkthroughs | | 🏛️ Education | Museum tours, historical site exploration | | 🛍️ E-Commerce | Product visualization, interactive showrooms | | 🎮 Gaming | Environmental exploration, scene backgrounds | | 🌍 Travel | Destination previews, interactive maps |
📋 Table of Contents
📦 Installation
Prerequisites
- React Native ≥ 0.60
- Expo ≥ 45 (or React Native CLI)
Via npm
npm install omniview-360Via yarn
yarn add omniview-360Via pnpm
pnpm add omniview-360Then link native modules (if not using Expo):
react-native link omniview-360🚀 Quick Start
import React from 'react';
import { View } from 'react-native';
import { OmniViewRenderer } from 'omniview-360';
export default function App() {
return (
<View style={{ flex: 1 }}>
<OmniViewRenderer
imageSource={require('./assets/panorama.jpg')}
initialLongitude={0}
initialLatitude={0}
/>
</View>
);
}📚 API Reference
OmniViewRenderer
Main component for rendering 360° panoramas.
Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| imageSource | string \| number | Required | Path or require() reference to equirectangular image (2:1 aspect ratio) |
| initialLongitude | number | 0 | Starting horizontal rotation (0–360°) |
| initialLatitude | number | 0 | Starting vertical rotation (–90 to 90°) |
| touchSensitivity | number | 0.3 | Touch gesture sensitivity (0.1–1.0) |
| enableGyroscope | boolean | false | Enable device motion-based rotation |
| onRotationChange | (lon, lat) => void | undefined | Callback when view rotates |
| hotspots | Hotspot[] | [] | Interactive point definitions |
| onHotspotPress | (id: string) => void | undefined | Callback when hotspot is tapped |
Hotspot Interface
interface Hotspot {
id: string; // Unique identifier
longitude: number; // 0–360 degrees
latitude: number; // –90 to 90 degrees
radius?: number; // Interactive radius in degrees
label?: string; // Optional tooltip text
}💡 Examples
Basic Panorama Viewer
import { OmniViewRenderer } from 'omniview-360';
export default function BasicViewer() {
return (
<OmniViewRenderer
imageSource={require('./panorama.jpg')}
/>
);
}With Rotation Tracking
import { useState } from 'react';
import { View, Text } from 'react-native';
import { OmniViewRenderer } from 'omniview-360';
export default function TrackedViewer() {
const [view, setView] = useState({ lon: 0, lat: 0 });
return (
<View style={{ flex: 1 }}>
<OmniViewRenderer
imageSource={require('./panorama.jpg')}
onRotationChange={(lon, lat) => setView({ lon, lat })}
/>
<Text>
Viewing: {view.lon.toFixed(0)}° × {view.lat.toFixed(0)}°
</Text>
</View>
);
}With Interactive Hotspots
import { OmniViewRenderer } from 'omniview-360';
const HOTSPOTS = [
{ id: 'door', longitude: 45, latitude: 0, label: 'Go to Hall' },
{ id: 'window', longitude: 270, latitude: -45, label: 'View Outside' },
];
export default function InteractiveViewer() {
const handleHotspot = (id) => {
console.log('Navigating to:', id);
// Load next panorama or trigger action
};
return (
<OmniViewRenderer
imageSource={require('./room.jpg')}
hotspots={HOTSPOTS}
onHotspotPress={handleHotspot}
/>
);
}Real Estate Property Tour
import { useState } from 'react';
import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';
import { OmniViewRenderer } from 'omniview-360';
const ROOMS = {
livingRoom: {
image: require('./rooms/living-room.jpg'),
hotspots: [
{ id: 'kitchen', longitude: 90, latitude: 0, label: 'Kitchen' },
{ id: 'bedroom', longitude: 270, latitude: 0, label: 'Bedroom' },
],
},
kitchen: {
image: require('./rooms/kitchen.jpg'),
hotspots: [
{ id: 'livingRoom', longitude: 270, latitude: 0, label: 'Back' },
],
},
};
export default function PropertyTour() {
const [currentRoom, setCurrentRoom] = useState('livingRoom');
const room = ROOMS[currentRoom];
return (
<View style={styles.container}>
<OmniViewRenderer
imageSource={room.image}
hotspots={room.hotspots}
onHotspotPress={(id) => setCurrentRoom(id)}
/>
<TouchableOpacity style={styles.button}>
<Text style={styles.buttonText}>Room: {currentRoom}</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1 },
button: { padding: 12, backgroundColor: '#007AFF' },
buttonText: { color: '#fff', fontWeight: 'bold' },
});⚡ Performance Tips
Image Optimization
- Use equirectangular images at 4096×2048 px or higher for best quality
- Compress with tools like ImageOptim or TinyPNG
- Consider WebP format for smaller file sizes
Device Considerations
- Gyroscope rendering may impact battery life
- Use
touchSensitivitybetween 0.2–0.5 for responsive controls - Test on actual devices (emulators may be slow)
Memory Management
- Dispose unused panoramas before loading new ones
- Use React's
useMemofor hotspot arrays if static - Consider lazy-loading panorama images
🔧 Troubleshooting
Panorama appears black
- Verify image path is correct
- Ensure image is equirectangular (2:1 aspect ratio)
- Check image exists in asset bundle
Touch gestures unresponsive
- Increase
touchSensitivityvalue - Ensure
PanResponderhandlers are properly wired - Test on real device (emulator may have issues)
Hotspots not appearing
- Verify longitude/latitude values (0–360 and –90 to 90)
- Check hotspots array is not empty
- Ensure
onHotspotPresscallback is defined
🤝 Contributing
We welcome contributions! Please:
- Fork the repo
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
📄 License
This project is licensed under the MIT License. See LICENSE for details.
🙏 Acknowledgments
- Built with Three.js for 3D rendering
- Inspired by panoramic viewing solutions in real estate and tourism
- Community feedback and contributions
Made with ❤️ for developers who want immersive experiences.
