You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
83 lines
2.5 KiB
TypeScript
83 lines
2.5 KiB
TypeScript
import {
|
|
VideoOverlay,
|
|
type CrossOrigin,
|
|
type LatLngBoundsExpression,
|
|
type VideoOverlayOptions,
|
|
} from 'leaflet';
|
|
import {
|
|
bool,
|
|
choice,
|
|
json,
|
|
num,
|
|
positional,
|
|
str,
|
|
type PropDef,
|
|
type Positional,
|
|
} from '../core/props.ts';
|
|
import { getBounds, urlProp, type Sourced } from '../core/shared-props.ts';
|
|
import {
|
|
WithProps,
|
|
type LeafletAddEventListener,
|
|
type LeafletElementConstructor,
|
|
type LeafletRemoveEventListener,
|
|
} from '../core/with-props.ts';
|
|
import type { PathEvents } from '../core/event-types.ts';
|
|
|
|
// Playback options live on the <video> element Leaflet builds, so live updates
|
|
// go there rather than through a Leaflet setter.
|
|
function media(
|
|
key: 'loop' | 'autoplay' | 'muted' | 'playsInline',
|
|
): (obj: VideoOverlay, value: boolean) => void {
|
|
return (obj, value) => {
|
|
const el = obj.getElement();
|
|
if (el) el[key] = value;
|
|
};
|
|
}
|
|
|
|
const PROPS: {
|
|
url: Positional<string, Sourced>;
|
|
bounds: Positional<LatLngBoundsExpression, VideoOverlay>;
|
|
opacity: PropDef<number>;
|
|
alt: PropDef<string>;
|
|
interactive: PropDef<boolean>;
|
|
crossOrigin: PropDef<CrossOrigin>;
|
|
loop: PropDef<boolean, VideoOverlay>;
|
|
autoplay: PropDef<boolean, VideoOverlay>;
|
|
muted: PropDef<boolean, VideoOverlay>;
|
|
playsInline: PropDef<boolean, VideoOverlay>;
|
|
zIndex: PropDef<number>;
|
|
className: PropDef<string>;
|
|
keepAspectRatio: PropDef<boolean>;
|
|
errorOverlayUrl: PropDef<string>;
|
|
} = {
|
|
url: urlProp,
|
|
bounds: positional(json<LatLngBoundsExpression, VideoOverlay>([], { get: getBounds })),
|
|
opacity: num(1.0),
|
|
alt: str(),
|
|
interactive: bool(),
|
|
crossOrigin: choice<CrossOrigin>(''),
|
|
loop: bool(false, { set: media('loop') }),
|
|
autoplay: bool(false, { set: media('autoplay') }),
|
|
muted: bool(false, { set: media('muted') }),
|
|
playsInline: bool(false, { attribute: 'playsinline', set: media('playsInline') }),
|
|
zIndex: num(),
|
|
className: str(),
|
|
keepAspectRatio: bool(true),
|
|
errorOverlayUrl: str(),
|
|
};
|
|
const Base: LeafletElementConstructor<VideoOverlay, typeof PROPS> = WithProps(PROPS);
|
|
|
|
export default class LeafletVideoOverlayElement extends Base {
|
|
declare readonly leafletObject?: VideoOverlay;
|
|
declare addEventListener: LeafletAddEventListener<PathEvents>;
|
|
declare removeEventListener: LeafletRemoveEventListener<PathEvents>;
|
|
|
|
createLeafletObject(options: VideoOverlayOptions): VideoOverlay {
|
|
return new VideoOverlay(this.url, this.bounds, options);
|
|
}
|
|
|
|
getElement(): HTMLVideoElement | undefined {
|
|
return this.leafletObject?.getElement();
|
|
}
|
|
}
|