1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 |
- import { h } from 'preact';
- import ActivityIndicator from './ActivityIndicator';
- import { useApiHost, useConfig } from '../api';
- import { useCallback, useEffect, useContext, useMemo, useRef, useState } from 'preact/hooks';
- export default function CameraImage({ camera, onload, searchParams = '' }) {
- const { data: config } = useConfig();
- const apiHost = useApiHost();
- const [availableWidth, setAvailableWidth] = useState(0);
- const [loadedSrc, setLoadedSrc] = useState(null);
- const containerRef = useRef(null);
- const { name, width, height } = config.cameras[camera];
- const aspectRatio = width / height;
- const resizeObserver = useMemo(() => {
- return new ResizeObserver((entries) => {
- window.requestAnimationFrame(() => {
- if (Array.isArray(entries) && entries.length) {
- setAvailableWidth(entries[0].contentRect.width);
- }
- });
- });
- }, [setAvailableWidth, width]);
- useEffect(() => {
- if (!containerRef.current) {
- return;
- }
- resizeObserver.observe(containerRef.current);
- }, [resizeObserver, containerRef.current]);
- const scaledHeight = useMemo(() => Math.min(Math.ceil(availableWidth / aspectRatio), height), [
- availableWidth,
- aspectRatio,
- height,
- ]);
- const img = useMemo(() => new Image(), [camera]);
- img.onload = useCallback(
- (event) => {
- const src = event.srcElement.currentSrc;
- setLoadedSrc(src);
- onload && onload(event);
- },
- [searchParams, onload]
- );
- useEffect(() => {
- if (!scaledHeight) {
- return;
- }
- img.src = `${apiHost}/api/${name}/latest.jpg?h=${scaledHeight}${searchParams ? `&${searchParams}` : ''}`;
- }, [apiHost, name, img, searchParams, scaledHeight]);
- return (
- <div ref={containerRef}>
- {loadedSrc ? (
- <img width={scaledHeight * aspectRatio} height={scaledHeight} src={loadedSrc} alt={name} />
- ) : (
- <ActivityIndicator />
- )}
- </div>
- );
- }
|