|
| 1 | +# FOV Viewer |
| 2 | + |
| 3 | +A browser-based tool that helps photographers visualize and compare field of view across different focal lengths and sensor sizes. Built for learning — understand how focal length and crop factor affect framing. |
| 4 | + |
| 5 | + |
| 6 | + |
| 7 | +## Features |
| 8 | + |
| 9 | +### Compare Up to 3 Lenses |
| 10 | +Start with one lens and add up to two more. Each lens gets its own color-coded overlay rectangle drawn on the image, showing exactly what that focal length would capture. Remove lenses you don't need with the X button. |
| 11 | + |
| 12 | +### Focal Length Control |
| 13 | +Continuous logarithmic slider from 14mm to 800mm with snap-to-preset behavior. Quick-select buttons for common focal lengths: 14mm, 20mm, 24mm, 35mm, 50mm, 85mm, 135mm, 200mm, 400mm, 600mm, 800mm. |
| 14 | + |
| 15 | +### Sensor / Crop Factor Presets |
| 16 | +Choose from 6 sensor sizes per lens — Medium Format (0.79x), Full Frame (1.0x), APS-C Nikon/Sony (1.5x), APS-C Canon (1.6x), Micro Four Thirds (2.0x), and 1" Sensor (2.7x). Equivalent focal length is displayed automatically when using a crop sensor. |
| 17 | + |
| 18 | +### Draggable Overlays |
| 19 | +Click and drag any FOV rectangle to reposition it on the image. Works on both desktop (mouse) and mobile (touch). Rectangles are constrained to stay within the photo boundaries. Hit "Center" to reset all positions. |
| 20 | + |
| 21 | +### Landscape / Portrait Orientation |
| 22 | +Toggle between landscape and portrait orientation to see how FOV changes when you rotate the camera. |
| 23 | + |
| 24 | +### 5 Sample Scenes |
| 25 | +Curated photos for different shooting scenarios — landscape, portrait, bird/wildlife, city street, and milky way/night sky. Each scene demonstrates different reasons you might choose one focal length over another. |
| 26 | + |
| 27 | +### Shareable Links |
| 28 | +Every setting is encoded in the URL query parameters. Change any control and the URL updates in real time. Copy the link to share your exact comparison with someone else. |
| 29 | + |
| 30 | +### Copy to Clipboard |
| 31 | +Export the current canvas view (image + overlay rectangles) as a PNG to your clipboard with one click. Falls back to file download if clipboard API isn't available. |
| 32 | + |
| 33 | +### Dark / Light Theme |
| 34 | +Dark theme by default (easier on the eyes for photo work). Toggle with the sun/moon button. Preference is saved to localStorage. |
| 35 | + |
| 36 | +### Responsive Design |
| 37 | +Full sidebar layout on desktop, stacked layout on mobile with full-width image canvas. Touch-draggable overlays on mobile. |
| 38 | + |
| 39 | +## Tech Stack |
| 40 | + |
| 41 | +- React 19 + TypeScript |
| 42 | +- Vite |
| 43 | +- Vitest + Testing Library |
| 44 | +- Canvas API for rendering |
| 45 | +- CSS custom properties for theming |
| 46 | +- Zero runtime dependencies beyond React |
| 47 | + |
| 48 | +## Development |
| 49 | + |
| 50 | +```bash |
| 51 | +npm install |
| 52 | +npm run dev |
| 53 | +``` |
| 54 | + |
| 55 | +Dev server runs at `http://localhost:5173/fov-viewer/`. |
| 56 | + |
| 57 | +## Testing |
| 58 | + |
| 59 | +```bash |
| 60 | +npm test # single run |
| 61 | +npm run test:watch # watch mode |
| 62 | +``` |
| 63 | + |
| 64 | +## Build |
| 65 | + |
| 66 | +```bash |
| 67 | +npm run build |
| 68 | +``` |
| 69 | + |
| 70 | +Static output goes to `dist/`. |
| 71 | + |
| 72 | +## Deployment |
| 73 | + |
| 74 | +Push to `main` — GitHub Actions automatically builds and deploys to GitHub Pages. |
| 75 | + |
| 76 | +To set up: |
| 77 | +1. Create a GitHub repo called `fov-viewer` |
| 78 | +2. Push this code to `main` |
| 79 | +3. Go to Settings > Pages > Source: "GitHub Actions" |
| 80 | + |
| 81 | +## URL Parameters |
| 82 | + |
| 83 | +All state is encoded in the URL for sharing: |
| 84 | + |
| 85 | +| Param | Description | Example | |
| 86 | +|-------|-------------|---------| |
| 87 | +| `a` | Lens A focal length (mm) | `a=20` | |
| 88 | +| `b` | Lens B focal length (mm) | `b=85` | |
| 89 | +| `c` | Lens C focal length (mm) | `c=200` | |
| 90 | +| `sa` | Lens A sensor | `sa=ff` | |
| 91 | +| `sb` | Lens B sensor | `sb=apsc_n` | |
| 92 | +| `sc` | Lens C sensor | `sc=m43` | |
| 93 | +| `img` | Image index (0-4) | `img=0` | |
| 94 | +| `theme` | `dark` or `light` | `theme=dark` | |
| 95 | + |
| 96 | +Sensor codes: `mf`, `ff`, `apsc_n`, `apsc_c`, `m43`, `1in` |
| 97 | + |
| 98 | +## License |
| 99 | + |
| 100 | +MIT |
0 commit comments