123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960 |
- import { h } from 'preact';
- import { ApiHost, Config } from '../context';
- import { useCallback, useEffect, useContext, useMemo, useRef, useState } from 'preact/hooks';
- export default function CameraImage({ camera, onload, searchParams = '' }) {
- const config = useContext(Config);
- const apiHost = useContext(ApiHost);
- 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.path[0].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} /> : null}
- </div>
- );
- }
|