import { css, html, LitElement, PropertyValueMap } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import Sylvester from "sylvester"; import { Zoom } from "../light9-timeline-audio"; import { PlainViewState } from "../Light9CursorCanvas"; import { getTopGraph } from "../RdfdbSyncedGraph"; import { show } from "../show_specific"; import { SyncedGraph } from "../SyncedGraph"; import { PlayerState } from "./PlayerState"; export { Light9TimelineAudio } from "../light9-timeline-audio"; export { Light9CursorCanvas } from "../Light9CursorCanvas"; export { RdfdbSyncedGraph } from "../RdfdbSyncedGraph"; export { ResourceDisplay } from "../ResourceDisplay"; const $V = Sylvester.Vector.create; async function postJson(url: string, jsBody: Object) { return fetch(url, { method: "POST", headers: { "Content-Type": "applcation/json" }, body: JSON.stringify(jsBody), }); } @customElement("light9-ascoltami-timeline") export class Light9AscoltamiTimeline extends LitElement { static styles = [ css` .timeRow { margin: 14px; position: relative; } #overview { height: 60px; } #zoomed { margin-top: 40px; height: 80px; } #cursor { position: absolute; left: 0; top: 0; width: 100%; height: 100%; } `, ]; graph!: SyncedGraph; @property() playerState: PlayerState = { duration: null, endOfSong: null, pausedSongTime: null, playing: null, song: null, wallStartTime: null, }; @property() playerTime: number = 0; @state() zoom: Zoom; @state() overviewZoom: Zoom; @state() viewState: PlainViewState | null = null; constructor() { super(); getTopGraph().then((g) => { this.graph = g; }); this.zoom = this.overviewZoom = { duration: null, t1: 0, t2: 1 }; } protected willUpdate(_changedProperties: PropertyValueMap): void { super.willUpdate(_changedProperties); if ((_changedProperties.has("playerState") || _changedProperties.has("playerTime")) && this.playerState !== null) { const duration = this.playerState.duration; const t = this.playerTime; if (duration !== null) { const timeRow = this.shadowRoot!.querySelector(".timeRow") as HTMLDivElement; if (timeRow != null) { this.updateZooms(duration, t, timeRow); } } } } updateZooms(duration: number, t: number, timeRow: HTMLDivElement) { this.overviewZoom = { duration: duration, t1: 0, t2: duration }; const t1 = t - 2; const t2 = t + 20; this.zoom = { duration: duration, t1, t2 }; const w = timeRow.offsetWidth; this.viewState = { zoomSpec: { t1: () => t1, t2: () => t2 }, cursor: { t: () => t }, audioY: () => 0, audioH: () => 60, zoomedTimeY: () => 60, zoomedTimeH: () => 40, fullZoomX: (sec: number) => (sec / duration) * w, zoomInX: (sec: number) => ((sec - t1) / (t2 - t1)) * w, mouse: { pos: () => $V([0, 0]) }, }; } render() { const song = this.playerState?.song; if (!song) return html`(spectrogram)`; return html`
`; } }