{"_id":"@bengrande/parallax-photo","_rev":"7-a552e8f5f1bc9e28613711ed5ce48108","name":"@bengrande/parallax-photo","dist-tags":{"latest":"1.5.0"},"versions":{"1.0.0":{"name":"@bengrande/parallax-photo","version":"1.0.0","license":"MIT","_id":"@bengrande/parallax-photo@1.0.0","maintainers":[{"name":"bengrande","email":"ben@grandes.ca"}],"homepage":"https://github.com/BenGrande/parallax-photo#readme","bugs":{"url":"https://github.com/BenGrande/parallax-photo/issues"},"dist":{"shasum":"06f21a06ab76eaf89b4cbfcc5a56eee658438ef6","tarball":"https://registry.npmjs.org/@bengrande/parallax-photo/-/parallax-photo-1.0.0.tgz","fileCount":5,"integrity":"sha512-PW7vqWj0QncFqhEPLA27WAS9G2evQIbiIL3E96MZFdozTdgSh9vBv2zzGlyERqHKePwev3VqquPWyDTL/78JTQ==","signatures":[{"sig":"MEQCIBhnNKYkCIiGclzVrc4JXOJ3RORm1a+g5EQ8ifz5+Hk/AiAwj1AYPSqhPwvFu8tcr0brHmValdoIvVSlUFDp30vlFg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":43659},"main":"splat-viewer.js","module":"splat-viewer.js","exports":{".":"./splat-viewer.js","./workers/*":"./workers/*"},"gitHead":"6fc58485b6772d61eeb6c5af8709ed5a205c0cbd","_npmUser":{"name":"bengrande","email":"ben@grandes.ca"},"repository":{"url":"git+https://github.com/BenGrande/parallax-photo.git","type":"git"},"_npmVersion":"10.8.2","description":"Lightweight 3D Gaussian Splat viewer with parallax, head-tracking, and device motion support","directories":{},"_nodeVersion":"20.20.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"peerDependencies":{"@mkkellogg/gaussian-splats-3d":"^0.4.7"},"_npmOperationalInternal":{"tmp":"tmp/parallax-photo_1.0.0_1772844438375_0.6825276852619118","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@bengrande/parallax-photo","version":"1.1.0","license":"MIT","_id":"@bengrande/parallax-photo@1.1.0","maintainers":[{"name":"bengrande","email":"ben@grandes.ca"}],"homepage":"https://github.com/BenGrande/parallax-photo#readme","bugs":{"url":"https://github.com/BenGrande/parallax-photo/issues"},"dist":{"shasum":"3202b3540715dffa6467f3eaa786d310a2310679","tarball":"https://registry.npmjs.org/@bengrande/parallax-photo/-/parallax-photo-1.1.0.tgz","fileCount":5,"integrity":"sha512-ECiLWoia+x6VgwmKKXZzns7yh2ce4awNS8RVAM9OW/CFWSIB6+J6AK8pLNsGrw60xER2GUsBTkaKyQhNHzC8/w==","signatures":[{"sig":"MEYCIQDCruyi/PsoX8Xt0EcFJ8qYp5R9jsjU1srFpjgl4yeBXAIhAMhurONgwY0h74tH56HPBBYFNtEpHTiqA1FpYWRpgZb3","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":43636},"main":"splat-viewer.js","module":"splat-viewer.js","exports":{".":"./splat-viewer.js","./workers/*":"./workers/*"},"gitHead":"5ac1ac851ff13fc97765aec566ac471d7389b327","_npmUser":{"name":"bengrande","email":"ben@grandes.ca"},"repository":{"url":"git+https://github.com/BenGrande/parallax-photo.git","type":"git"},"_npmVersion":"10.8.2","description":"Lightweight 3D Gaussian Splat viewer with parallax, head-tracking, and device motion support","directories":{},"_nodeVersion":"20.20.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"peerDependencies":{"@mkkellogg/gaussian-splats-3d":"^0.4.7"},"_npmOperationalInternal":{"tmp":"tmp/parallax-photo_1.1.0_1772848082508_0.9647550712574919","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@bengrande/parallax-photo","version":"1.2.0","license":"MIT","_id":"@bengrande/parallax-photo@1.2.0","maintainers":[{"name":"bengrande","email":"ben@grandes.ca"}],"homepage":"https://github.com/BenGrande/parallax-photo#readme","bugs":{"url":"https://github.com/BenGrande/parallax-photo/issues"},"dist":{"shasum":"e83eec9e61a632e28a852352e0e85c95163df44b","tarball":"https://registry.npmjs.org/@bengrande/parallax-photo/-/parallax-photo-1.2.0.tgz","fileCount":5,"integrity":"sha512-wOpl6uD19ktyq29sO/5QM9p8WDnh9IJcT/8BJFQ4hPDOYqYkM+tm3TDASMzFEszLv/Op2sa5/85y600OvsLFHQ==","signatures":[{"sig":"MEUCIQCbzKCAUR8yyVF0DZUNDUpk7vRDbTAdE72dloPVgKXxewIgScM7Zcqp6u4SDzgU29FuBeJqmdR4sb8IGxJklaspDZY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":43076},"main":"splat-viewer.js","module":"splat-viewer.js","exports":{".":"./splat-viewer.js","./workers/*":"./workers/*"},"gitHead":"1cc0d49b164d0790fd9a27978cfbc92b895040b0","_npmUser":{"name":"bengrande","email":"ben@grandes.ca"},"repository":{"url":"git+https://github.com/BenGrande/parallax-photo.git","type":"git"},"_npmVersion":"10.8.2","description":"Lightweight 3D Gaussian Splat viewer with parallax, head-tracking, and device motion support","directories":{},"_nodeVersion":"20.20.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"peerDependencies":{"@mkkellogg/gaussian-splats-3d":"^0.4.7"},"_npmOperationalInternal":{"tmp":"tmp/parallax-photo_1.2.0_1772853903916_0.3907745046341027","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@bengrande/parallax-photo","version":"1.3.0","license":"MIT","_id":"@bengrande/parallax-photo@1.3.0","maintainers":[{"name":"bengrande","email":"ben@grandes.ca"}],"homepage":"https://github.com/BenGrande/parallax-photo#readme","bugs":{"url":"https://github.com/BenGrande/parallax-photo/issues"},"dist":{"shasum":"0f9fd5fd79070a52581113d7d3df4c779079b779","tarball":"https://registry.npmjs.org/@bengrande/parallax-photo/-/parallax-photo-1.3.0.tgz","fileCount":5,"integrity":"sha512-XZVYPrfvvZDbnhE4Vx108KhlRCKu/n+KkIno8TBbdZrt3ZJNR0rajRykLv3gmjejqngvPTX65T9EmNwu07JV8g==","signatures":[{"sig":"MEQCICIa15bAr7eOrHeZT7Iv6fJzfA6zHNmSW8zsRCUlElf+AiAX4MpsUswExM1I44OLTKQwPOc5MoiE/pDUP4JGMT1K/A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":43941},"main":"splat-viewer.js","module":"splat-viewer.js","exports":{".":"./splat-viewer.js","./workers/*":"./workers/*"},"gitHead":"3b3cd3540de78120982f762e3459e44cf6c16fab","_npmUser":{"name":"bengrande","email":"ben@grandes.ca"},"repository":{"url":"git+https://github.com/BenGrande/parallax-photo.git","type":"git"},"_npmVersion":"10.8.2","description":"Lightweight 3D Gaussian Splat viewer with parallax, head-tracking, and device motion support","directories":{},"_nodeVersion":"20.20.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"peerDependencies":{"@mkkellogg/gaussian-splats-3d":"^0.4.7"},"_npmOperationalInternal":{"tmp":"tmp/parallax-photo_1.3.0_1772854878390_0.4686576021201627","host":"s3://npm-registry-packages-npm-production"}},"1.4.0":{"name":"@bengrande/parallax-photo","version":"1.4.0","license":"MIT","_id":"@bengrande/parallax-photo@1.4.0","maintainers":[{"name":"bengrande","email":"ben@grandes.ca"}],"homepage":"https://github.com/BenGrande/parallax-photo#readme","bugs":{"url":"https://github.com/BenGrande/parallax-photo/issues"},"dist":{"shasum":"9e7eb9e0fb58d129a13c5a42f0a739d6e8a3fd18","tarball":"https://registry.npmjs.org/@bengrande/parallax-photo/-/parallax-photo-1.4.0.tgz","fileCount":6,"integrity":"sha512-fRLEMqMYwV88XnaVIRTbY8+YdD7QkqKTWjzKO1MoPmY3yx7cJ8NOScRVie0KOdkwR7uZnRKeXyU5qVhJaZ19xA==","signatures":[{"sig":"MEUCIQDBO3fj0uYLnaopRW/t18uGFCrFGwM+yUpxCD6qPGZ4QAIgW3sLqeLza1IClmseSLH6Vj74vGz7RxVf2yky2q3X5SE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":48132},"main":"splat-viewer.js","module":"splat-viewer.js","exports":{".":"./splat-viewer.js","./workers/*":"./workers/*","./esbuild-plugin":"./esbuild-plugin.js"},"gitHead":"30dec447150909b1788e1c6a525ccb39f559a1e1","_npmUser":{"name":"bengrande","email":"ben@grandes.ca"},"repository":{"url":"git+https://github.com/BenGrande/parallax-photo.git","type":"git"},"_npmVersion":"10.8.2","description":"Lightweight 3D Gaussian Splat viewer with parallax, head-tracking, and device motion support","directories":{},"_nodeVersion":"20.20.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"peerDependencies":{"@mkkellogg/gaussian-splats-3d":"^0.4.7"},"_npmOperationalInternal":{"tmp":"tmp/parallax-photo_1.4.0_1772855924525_0.8600854999507237","host":"s3://npm-registry-packages-npm-production"}},"1.4.1":{"name":"@bengrande/parallax-photo","version":"1.4.1","license":"MIT","_id":"@bengrande/parallax-photo@1.4.1","maintainers":[{"name":"bengrande","email":"ben@grandes.ca"}],"homepage":"https://github.com/BenGrande/parallax-photo#readme","bugs":{"url":"https://github.com/BenGrande/parallax-photo/issues"},"dist":{"shasum":"37f6de764b5fdbef8a14be6d8dc5f7d3734e03ef","tarball":"https://registry.npmjs.org/@bengrande/parallax-photo/-/parallax-photo-1.4.1.tgz","fileCount":6,"integrity":"sha512-hMrTGm62A5yqxWVT8cFGdvpLi4G0Dc2s17hl5oeW3FRUYK7vtGUu6ggldQSaz/Lal5B5dh+sb6zgae9ZzjW7IQ==","signatures":[{"sig":"MEYCIQCsyujU6aeZwqZNxgC3KvTOvA2lkK/UP145PnRC4UVvVQIhAJatrWOexcpq70GAd293Kb3y9maIYpK5eL7BspdeJVoI","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":48152},"main":"splat-viewer.js","type":"module","module":"splat-viewer.js","exports":{".":"./splat-viewer.js","./workers/*":"./workers/*","./esbuild-plugin":"./esbuild-plugin.js"},"gitHead":"5ab7029f02191daf98a28c7924d1e3fde3d4a329","_npmUser":{"name":"bengrande","email":"ben@grandes.ca"},"repository":{"url":"git+https://github.com/BenGrande/parallax-photo.git","type":"git"},"_npmVersion":"10.8.2","description":"Lightweight 3D Gaussian Splat viewer with parallax, head-tracking, and device motion support","directories":{},"_nodeVersion":"20.20.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"peerDependencies":{"@mkkellogg/gaussian-splats-3d":"^0.4.7"},"_npmOperationalInternal":{"tmp":"tmp/parallax-photo_1.4.1_1772855961595_0.10278453051976122","host":"s3://npm-registry-packages-npm-production"}},"1.5.0":{"name":"@bengrande/parallax-photo","version":"1.5.0","description":"Lightweight 3D Gaussian Splat viewer with parallax, head-tracking, and device motion support","type":"module","main":"splat-viewer.js","module":"splat-viewer.js","exports":{".":"./splat-viewer.js","./esbuild-plugin":"./esbuild-plugin.js","./workers/*":"./workers/*"},"repository":{"type":"git","url":"git+https://github.com/BenGrande/parallax-photo.git"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"license":"MIT","peerDependencies":{"@mkkellogg/gaussian-splats-3d":"^0.4.7"},"_id":"@bengrande/parallax-photo@1.5.0","gitHead":"72563f95c7d0448f2de36e6d36a24a00dab9e368","bugs":{"url":"https://github.com/BenGrande/parallax-photo/issues"},"homepage":"https://github.com/BenGrande/parallax-photo#readme","_nodeVersion":"20.20.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-on0g/s+nGToQpl9sPUy0GR2ahX4VYJtHbJqJDunP4oZtUpDbYS9BlZTH+mLQ+9HI1ZTBxBLDb+7xFGgVtIdevA==","shasum":"81f07c75afb1646e87e1efd4287f0112c135efba","tarball":"https://registry.npmjs.org/@bengrande/parallax-photo/-/parallax-photo-1.5.0.tgz","fileCount":6,"unpackedSize":48571,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCIHEnp2i4/D7bxPVf0JyqBsPkB0hiDR4ZOqvHUbJJ3FgIhAI2JJMa9cDDW47AwmHkzF9Go5eXVjc5F8JPiqr63u3RJ"}]},"_npmUser":{"name":"bengrande","email":"ben@grandes.ca"},"directories":{},"maintainers":[{"name":"bengrande","email":"ben@grandes.ca"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/parallax-photo_1.5.0_1773076295027_0.3135230666929334"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-07T00:47:18.278Z","modified":"2026-03-09T17:11:35.300Z","1.0.0":"2026-03-07T00:47:18.526Z","1.1.0":"2026-03-07T01:48:02.698Z","1.2.0":"2026-03-07T03:25:04.076Z","1.3.0":"2026-03-07T03:41:18.520Z","1.4.0":"2026-03-07T03:58:44.666Z","1.4.1":"2026-03-07T03:59:21.729Z","1.5.0":"2026-03-09T17:11:35.191Z"},"bugs":{"url":"https://github.com/BenGrande/parallax-photo/issues"},"license":"MIT","homepage":"https://github.com/BenGrande/parallax-photo#readme","repository":{"type":"git","url":"git+https://github.com/BenGrande/parallax-photo.git"},"description":"Lightweight 3D Gaussian Splat viewer with parallax, head-tracking, and device motion support","maintainers":[{"name":"bengrande","email":"ben@grandes.ca"}],"readme":"# SplatViewer\n\nA lightweight JavaScript library for viewing 3D Gaussian Splats with parallax effects.\n\n## Features\n\n- 📦 Zero-config CDN import with built-in demo\n- 🖼️ Placeholder image with smooth transition\n- 📱 Device motion parallax (gyroscope)\n- 🖱️ Mouse parallax for desktop\n- 🎮 Pan, rotate, zoom controls\n- 📊 Built-in loading bar\n- ⚡ Built on [@mkkellogg/gaussian-splats-3d](https://github.com/mkkellogg/GaussianSplats3D)\n\n## Installation\n\n### CDN (jsDelivr)\n\n```html\n<script type=\"module\">\n  import { SplatViewer } from 'https://cdn.jsdelivr.net/gh/BenGrande/parallax-photo@main/splat-viewer.js';\n</script>\n```\n\n### Local\n\n```html\n<script type=\"module\">\n  import { SplatViewer } from './splat-viewer.js';\n</script>\n```\n\n## Quick Start\n\n### Zero-Config Demo\n\n```javascript\nimport { SplatViewer } from 'https://cdn.jsdelivr.net/gh/BenGrande/parallax-photo@main/splat-viewer.js';\n\n// No options = loads built-in demo scene\nconst viewer = new SplatViewer('#container');\nawait viewer.load();\n```\n\n### Custom Scene\n\n```javascript\nimport { SplatViewer } from './splat-viewer.js';\n\nconst viewer = new SplatViewer('#container', {\n  plyUrl: 'scene.ply',\n  placeholderImage: 'photo.jpg'\n});\n\nawait viewer.load();\n```\n\n## Options\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `plyUrl` | string | null | URL to the .ply splat file |\n| `placeholderImage` | string | null | Image to show while loading |\n| `transitionDuration` | number | 1200 | Fade transition duration (ms) |\n| `cameraPosition` | array | [0,0,0] | Initial camera position [x,y,z] |\n| `cameraLookAt` | array | [0,0,50] | Camera look-at target [x,y,z] |\n| `cameraUp` | array | [0,-1,0] | Camera up vector |\n| `fov` | number | 48.5 | Field of view (degrees) |\n| `enableControls` | boolean | true | Enable built-in orbit controls (set true, then call disableControls() after load for head-tracking-only setups) |\n| `perspectiveIntensity` | number | 0.5 | Parallax effect strength |\n| `showLoadingBar` | boolean | true | Show built-in loading progress bar |\n| `loadingBarColor` | string | '#4a90d9' | Loading bar color |\n| `loadingBarHeight` | string | '3px' | Loading bar height |\n| `onProgress` | function | null | Loading progress callback (percent) |\n| `onLoad` | function | null | Called when splat is loaded |\n| `onFallback` | function | null | Called when switching to 2D fallback |\n| `onError` | function | null | Called on error |\n\n## Methods\n\n### Loading\n\n```javascript\n// Load splat (uses plyUrl from options, or defaults to demo)\nawait viewer.load();\n\n// Load specific URL\nawait viewer.load('other-scene.ply');\n```\n\n### Perspective (Parallax)\n\n```javascript\n// Subtle view shift - like moving your head\nviewer.perspective(offsetX, offsetY, offsetZ);\n\n// Adjust parallax intensity\nviewer.setPerspectiveIntensity(0.8);\n```\n\n### Device Motion\n\n```javascript\n// Enable gyroscope-based parallax\nviewer.enableDeviceMotion();\n\n// Disable\nviewer.disableDeviceMotion();\n\n// Recalibrate (set current orientation as neutral)\nviewer.calibrateDeviceMotion();\n```\n\n### Camera Controls\n\n```javascript\n// Pan (translate)\nviewer.pan(deltaX, deltaY);\n\n// Rotate (orbit)\nviewer.rotate(deltaYaw, deltaPitch);\n\n// Zoom\nviewer.zoom(delta);\n\n// Reset to initial position\nviewer.reset();\n\n// Direct position control\nviewer.setCameraPosition(x, y, z);\nviewer.getCameraPosition(); // returns [x, y, z]\n\n// Adjust control speeds\nviewer.setSpeed(orbit, pan, zoom);\n```\n\n### Disable Controls\n\n```javascript\n// After loading, remove all keyboard/mouse handlers (for head-tracking-only setups)\nviewer.disableControls();\n```\n\n### Fallback Mode\n\n```javascript\n// Force 2D fallback mode (for low-memory devices)\nviewer.forceFallback();\n\n// Check mode\nviewer.isFallbackMode; // boolean\n```\n\n### Cleanup\n\n```javascript\nviewer.dispose();\n```\n\n## Device Motion Example\n\n```javascript\nconst viewer = new SplatViewer('#container', {\n  plyUrl: 'scene.ply',\n  placeholderImage: 'photo.jpg',\n  perspectiveIntensity: 0.8\n});\n\nawait viewer.load();\n\n// Request permission and enable (required for iOS)\ndocument.querySelector('#enableMotion').onclick = async () => {\n  if (typeof DeviceOrientationEvent?.requestPermission === 'function') {\n    const permission = await DeviceOrientationEvent.requestPermission();\n    if (permission !== 'granted') return;\n  }\n  viewer.enableDeviceMotion();\n};\n```\n\n## Mouse Parallax Example\n\n```javascript\ndocument.addEventListener('mousemove', (e) => {\n  if (!viewer.isLoaded) return;\n  \n  const cx = window.innerWidth / 2;\n  const cy = window.innerHeight / 2;\n  const offsetX = (e.clientX - cx) / cx;\n  const offsetY = (e.clientY - cy) / cy;\n  \n  viewer.perspective(offsetX * 0.15, offsetY * 0.15);\n});\n```\n\n## Chrome Extension Support\n\nChrome extensions block inline Blob workers and may capture keyboard events. This package includes an esbuild plugin that patches the underlying library for full compatibility.\n\n```javascript\n// esbuild.config.mjs\nimport { chromeExtensionPlugin } from '@bengrande/parallax-photo/esbuild-plugin';\n\nesbuild.build({\n  // ...your config\n  plugins: [\n    chromeExtensionPlugin({\n      workerPath: 'lib/workers',        // where worker files are served from (default)\n      patchKeyboardHandlers: true,       // remove WASD/mouse handlers (default)\n    }),\n  ],\n});\n```\n\nYou also need to copy the worker files to your extension and make them web-accessible:\n\n```bash\ncp node_modules/@bengrande/parallax-photo/workers/* lib/workers/\n```\n\n```json\n// manifest.json\n{\n  \"content_security_policy\": {\n    \"extension_pages\": \"script-src 'self' 'wasm-unsafe-eval'; worker-src 'self'\"\n  },\n  \"web_accessible_resources\": [{\n    \"resources\": [\"lib/workers/*\"],\n    \"matches\": [\"<all_urls>\"]\n  }]\n}\n```\n\n## Generating PLY Files\n\nUse [Apple's SHARP](https://github.com/apple/ml-sharp) to generate 3D Gaussian Splats from a single photo:\n\n```bash\nsharp predict --input-path photo.jpg --output-path output/ --device mps\n```\n\n## Default Demo Scene\n\nThe built-in demo uses a foggy mountain photo:\n- **Photo by [v2osk](https://unsplash.com/@v2osk) on [Unsplash](https://unsplash.com/photos/foggy-mountain-summit-1Z2niiBPg5A)**\n\n## License\n\nMIT\n","readmeFilename":"README.md"}