npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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.

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-360

Via yarn

yarn add omniview-360

Via pnpm

pnpm add omniview-360

Then 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

  1. 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
  2. Device Considerations

    • Gyroscope rendering may impact battery life
    • Use touchSensitivity between 0.2–0.5 for responsive controls
    • Test on actual devices (emulators may be slow)
  3. Memory Management

    • Dispose unused panoramas before loading new ones
    • Use React's useMemo for 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 touchSensitivity value
  • Ensure PanResponder handlers 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 onHotspotPress callback is defined

🤝 Contributing

We welcome contributions! Please:

  1. Fork the repo
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit changes (git commit -m 'Add amazing feature')
  4. Push to branch (git push origin feature/amazing-feature)
  5. 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.

Report IssuesRequest FeaturesView Changelog