mirror of
				https://github.com/blakeblackshear/frigate.git
				synced 2025-10-27 10:52:11 +01:00 
			
		
		
		
	Add ability to zoom in to live and recordings views (#10475)
* Make live view zoomable * Add zooming to full recordings
This commit is contained in:
		
							parent
							
								
									c66f552280
								
							
						
					
					
						commit
						f5a26c5962
					
				
							
								
								
									
										14
									
								
								web/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										14
									
								
								web/package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -52,6 +52,7 @@ | |||||||
|         "react-tracked": "^1.7.11", |         "react-tracked": "^1.7.11", | ||||||
|         "react-transition-group": "^4.4.5", |         "react-transition-group": "^4.4.5", | ||||||
|         "react-use-websocket": "^4.7.0", |         "react-use-websocket": "^4.7.0", | ||||||
|  |         "react-zoom-pan-pinch": "^3.4.3", | ||||||
|         "recoil": "^0.7.7", |         "recoil": "^0.7.7", | ||||||
|         "scroll-into-view-if-needed": "^3.1.0", |         "scroll-into-view-if-needed": "^3.1.0", | ||||||
|         "sonner": "^1.4.0", |         "sonner": "^1.4.0", | ||||||
| @ -6694,6 +6695,19 @@ | |||||||
|         "react-dom": ">= 18.0.0" |         "react-dom": ">= 18.0.0" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "node_modules/react-zoom-pan-pinch": { | ||||||
|  |       "version": "3.4.3", | ||||||
|  |       "resolved": "https://registry.npmjs.org/react-zoom-pan-pinch/-/react-zoom-pan-pinch-3.4.3.tgz", | ||||||
|  |       "integrity": "sha512-x5MFlfAx2D6NTpZu8OISqc2nYn4p+YEaM1p21w7S/VE1wbVzK8vRzTo9Bj1ydufa649MuP7JBRM3vvj1RftFZw==", | ||||||
|  |       "engines": { | ||||||
|  |         "node": ">=8", | ||||||
|  |         "npm": ">=5" | ||||||
|  |       }, | ||||||
|  |       "peerDependencies": { | ||||||
|  |         "react": "*", | ||||||
|  |         "react-dom": "*" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "node_modules/read-cache": { |     "node_modules/read-cache": { | ||||||
|       "version": "1.0.0", |       "version": "1.0.0", | ||||||
|       "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", |       "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", | ||||||
|  | |||||||
| @ -57,6 +57,7 @@ | |||||||
|     "react-tracked": "^1.7.11", |     "react-tracked": "^1.7.11", | ||||||
|     "react-transition-group": "^4.4.5", |     "react-transition-group": "^4.4.5", | ||||||
|     "react-use-websocket": "^4.7.0", |     "react-use-websocket": "^4.7.0", | ||||||
|  |     "react-zoom-pan-pinch": "^3.4.3", | ||||||
|     "recoil": "^0.7.7", |     "recoil": "^0.7.7", | ||||||
|     "scroll-into-view-if-needed": "^3.1.0", |     "scroll-into-view-if-needed": "^3.1.0", | ||||||
|     "sonner": "^1.4.0", |     "sonner": "^1.4.0", | ||||||
|  | |||||||
| @ -27,6 +27,7 @@ import { | |||||||
| } from "react-icons/md"; | } from "react-icons/md"; | ||||||
| import useKeyboardListener from "@/hooks/use-keyboard-listener"; | import useKeyboardListener from "@/hooks/use-keyboard-listener"; | ||||||
| import { Slider } from "../ui/slider-volume"; | import { Slider } from "../ui/slider-volume"; | ||||||
|  | import { TransformComponent, TransformWrapper } from "react-zoom-pan-pinch"; | ||||||
| 
 | 
 | ||||||
| const HLS_MIME_TYPE = "application/vnd.apple.mpegurl" as const; | const HLS_MIME_TYPE = "application/vnd.apple.mpegurl" as const; | ||||||
| const unsupportedErrorCodes = [ | const unsupportedErrorCodes = [ | ||||||
| @ -169,6 +170,8 @@ export default function HlsVideoPlayer({ | |||||||
|       } |       } | ||||||
|       onClick={isDesktop ? undefined : () => setControls(!controls)} |       onClick={isDesktop ? undefined : () => setControls(!controls)} | ||||||
|     > |     > | ||||||
|  |       <TransformWrapper minScale={1.0}> | ||||||
|  |         <TransformComponent> | ||||||
|           <video |           <video | ||||||
|             ref={videoRef} |             ref={videoRef} | ||||||
|             className="size-full rounded-2xl" |             className="size-full rounded-2xl" | ||||||
| @ -182,7 +185,9 @@ export default function HlsVideoPlayer({ | |||||||
| 
 | 
 | ||||||
|               if (isMobile) { |               if (isMobile) { | ||||||
|                 setControls(true); |                 setControls(true); | ||||||
|             setMobileCtrlTimeout(setTimeout(() => setControls(false), 4000)); |                 setMobileCtrlTimeout( | ||||||
|  |                   setTimeout(() => setControls(false), 4000), | ||||||
|  |                 ); | ||||||
|               } |               } | ||||||
|             }} |             }} | ||||||
|             onPlaying={onPlaying} |             onPlaying={onPlaying} | ||||||
| @ -211,6 +216,8 @@ export default function HlsVideoPlayer({ | |||||||
|               } |               } | ||||||
|             }} |             }} | ||||||
|           /> |           /> | ||||||
|  |         </TransformComponent> | ||||||
|  |       </TransformWrapper> | ||||||
|       <VideoControls |       <VideoControls | ||||||
|         video={videoRef.current} |         video={videoRef.current} | ||||||
|         isPlaying={isPlaying} |         isPlaying={isPlaying} | ||||||
|  | |||||||
| @ -55,6 +55,7 @@ import { | |||||||
|   MdZoomOut, |   MdZoomOut, | ||||||
| } from "react-icons/md"; | } from "react-icons/md"; | ||||||
| import { useNavigate } from "react-router-dom"; | import { useNavigate } from "react-router-dom"; | ||||||
|  | import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch"; | ||||||
| import useSWR from "swr"; | import useSWR from "swr"; | ||||||
| 
 | 
 | ||||||
| type LiveCameraViewProps = { | type LiveCameraViewProps = { | ||||||
| @ -263,9 +264,11 @@ export default function LiveCameraView({ camera }: LiveCameraViewProps) { | |||||||
|             aspectRatio: aspectRatio, |             aspectRatio: aspectRatio, | ||||||
|           }} |           }} | ||||||
|         > |         > | ||||||
|  |           <TransformWrapper minScale={1.0}> | ||||||
|  |             <TransformComponent> | ||||||
|               <LivePlayer |               <LivePlayer | ||||||
|                 key={camera.name} |                 key={camera.name} | ||||||
|             className={`${fullscreen ? "*:rounded-none" : ""}`} |                 className={`m-1 ${fullscreen ? "*:rounded-none" : ""}`} | ||||||
|                 windowVisible |                 windowVisible | ||||||
|                 showStillWithoutActivity={false} |                 showStillWithoutActivity={false} | ||||||
|                 cameraConfig={camera} |                 cameraConfig={camera} | ||||||
| @ -273,6 +276,8 @@ export default function LiveCameraView({ camera }: LiveCameraViewProps) { | |||||||
|                 micEnabled={mic} |                 micEnabled={mic} | ||||||
|                 preferredLiveMode={preferredLiveMode} |                 preferredLiveMode={preferredLiveMode} | ||||||
|               /> |               /> | ||||||
|  |             </TransformComponent> | ||||||
|  |           </TransformWrapper> | ||||||
|         </div> |         </div> | ||||||
|         {camera.onvif.host != "" && <PtzControlPanel camera={camera.name} />} |         {camera.onvif.host != "" && <PtzControlPanel camera={camera.name} />} | ||||||
|       </div> |       </div> | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user