Files @ e7e03c203c99
Branch filter:

Location: light9/web/ascoltami/Light9AscoltamiTimeline.ts

drewp@bigasterisk.com
resize cursor canvas for 400px tall spectros. fix canvas resolution code
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 { PlainerViewState, 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: 400px;
      }
      #zoomed {
        margin-top: 40px;
        height: 400px;
      }
      #cursor {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
      }
      #timeSlider {
        height: 0;
      }
    `,
  ];
  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: PlainerViewState | null = null;
  constructor() {
    super();
    getTopGraph().then((g) => {
      this.graph = g;
    });
    this.zoom = this.overviewZoom = { duration: null, t1: 0, t2: 1 };
  }
  protected willUpdate(_changedProperties: PropertyValueMap<this>): 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: 400,
      zoomedTimeY: 400,
      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`
      <div class="timeRow">
        <div id="timeSlider"></div>
        <light9-timeline-audio id="overview" .show=${show} .song=${song} .zoom=${this.overviewZoom}> </light9-timeline-audio>
        <light9-timeline-audio id="zoomed" .show=${show} .song=${song} .zoom=${this.zoom}></light9-timeline-audio>
        <light9-cursor-canvas id="cursor" .viewState=${this.viewState}></light9-cursor-canvas>
      </div>
    `;
  }
}