Changeset - e7e03c203c99
[Not reviewed]
default
0 3 0
drewp@bigasterisk.com - 8 months ago 2024-06-01 20:32:58
drewp@bigasterisk.com
resize cursor canvas for 400px tall spectros. fix canvas resolution code
3 files changed with 49 insertions and 34 deletions:
0 comments (0 inline, 0 general)
web/Light9CursorCanvas.ts
Show inline comments
 
@@ -18,12 +18,23 @@ export interface PlainViewState {
 
  audioH: () => number;
 
  zoomedTimeY: () => number; // not what you think- it's the zone in between
 
  zoomedTimeH: () => number;
 
  mouse: { pos: () => Vector };
 
}
 

	
 
export interface PlainerViewState {
 
  zoomSpec: { t1: number; t2: number };
 
  fullZoomX: (t: number) => number;
 
  zoomInX: (t: number) => number;
 
  cursor: { t: number };
 
  audioY: number;
 
  audioH: number;
 
  zoomedTimeY: number; // not what you think- it's the zone in between
 
  zoomedTimeH: number;
 
  mouse: { pos: Vector };
 
}
 
// For cases where you have a zoomed-out view on top of a zoomed-in view,
 
// overlay this element and it'll draw a time cursor on both views.
 
@customElement("light9-cursor-canvas")
 
export class Light9CursorCanvas extends LitElement {
 
  cursorPath: null | {
 
    top0: Vector;
 
@@ -36,76 +47,76 @@ export class Light9CursorCanvas extends 
 
    bot1: Vector;
 
  } = null;
 
  canvasEl!: HTMLCanvasElement;
 
  ctx!: CanvasRenderingContext2D;
 
  offsetWidth: any;
 
  offsetHeight: any;
 
  @property() viewState: PlainViewState | null = null;
 
  @property() viewState: PlainerViewState | null = null;
 
  static styles = [
 
    css`
 
      :host {
 
        display: inline-block;
 
      }
 
      canvas {
 
        width: 100%;
 
        height: 100%;
 
        
 
      }
 
    `,
 
  ];
 
  resizeObserver!: ResizeObserver;
 
  render() {
 
    return html`<canvas></canvas>`;
 
  }
 

	
 
  updated(changedProperties: PropertyValues) {
 
    if (changedProperties.has("viewState")) {
 
      this.redrawCursor();
 
    }
 
  }
 
  connectedCallback() {
 
    super.connectedCallback();
 
    window.addEventListener("resize", this.onResize);
 
    this.onResize();
 
    this.resizeObserver = new ResizeObserver(this.onResize.bind(this));
 
    this.resizeObserver.observe(this);
 
  }
 

	
 
  firstUpdated() {
 
    this.canvasEl = this.shadowRoot!.firstElementChild as HTMLCanvasElement;
 
    this.onResize();
 
    this.ctx = this.canvasEl.getContext("2d")!;
 
  }
 

	
 
  disconnectedCallback() {
 
    window.removeEventListener("resize", this.onResize);
 
    super.disconnectedCallback();
 
    this.resizeObserver.unobserve(this);
 
  }
 

	
 
  // onViewState() {
 
  //   ko.computed(this.redrawCursor.bind(this));
 
  // }
 

	
 
  onResize() {
 
    log('onResize', this.clientWidth, this.clientHeight);
 
    if (!this.canvasEl) {
 
      return;
 
    }
 
    this.canvasEl.width = this.offsetWidth;
 
    this.canvasEl.height = this.offsetHeight;
 
    this.canvasEl.width = this.clientWidth;
 
    this.canvasEl.height = this.clientHeight;
 
    this.redrawCursor();
 
  }
 

	
 
  redrawCursor() {
 
    const vs = this.viewState;
 
    if (!vs) {
 
      return;
 
    }
 
    const dependOn = [vs.zoomSpec.t1(), vs.zoomSpec.t2()];
 
    const xZoomedOut = vs.fullZoomX(vs.cursor.t());
 
    const xZoomedIn = vs.zoomInX(vs.cursor.t());
 
    const xZoomedOut = vs.fullZoomX(vs.cursor.t);
 
    const xZoomedIn = vs.zoomInX(vs.cursor.t);
 

	
 
    this.cursorPath = {
 
      top0: $V([xZoomedOut, vs.audioY()]),
 
      top1: $V([xZoomedOut, vs.audioY() + vs.audioH()]),
 
      mid0: $V([xZoomedIn + 2, vs.zoomedTimeY() + vs.zoomedTimeH()]),
 
      mid1: $V([xZoomedIn - 2, vs.zoomedTimeY() + vs.zoomedTimeH()]),
 
      mid2: $V([xZoomedOut - 1, vs.audioY() + vs.audioH()]),
 
      mid3: $V([xZoomedOut + 1, vs.audioY() + vs.audioH()]),
 
      bot0: $V([xZoomedIn, vs.zoomedTimeY() + vs.zoomedTimeH()]),
 
      top0: $V([xZoomedOut, vs.audioY]),
 
      top1: $V([xZoomedOut, vs.audioY + vs.audioH]),
 
      mid0: $V([xZoomedIn + 2, vs.zoomedTimeY + vs.zoomedTimeH]),
 
      mid1: $V([xZoomedIn - 2, vs.zoomedTimeY + vs.zoomedTimeH]),
 
      mid2: $V([xZoomedOut - 1, vs.audioY + vs.audioH]),
 
      mid3: $V([xZoomedOut + 1, vs.audioY + vs.audioH]),
 
      bot0: $V([xZoomedIn, vs.zoomedTimeY + vs.zoomedTimeH]),
 
      bot1: $V([xZoomedIn, this.offsetHeight]),
 
    };
 
    this.redraw();
 
  }
 

	
 
  redraw() {
 
@@ -114,13 +125,13 @@ export class Light9CursorCanvas extends 
 
    }
 
    this.ctx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);
 

	
 
    this.ctx.strokeStyle = "#fff";
 
    this.ctx.lineWidth = 0.5;
 
    this.ctx.beginPath();
 
    const mouse = this.viewState.mouse.pos();
 
    const mouse = this.viewState.mouse.pos;
 
    line(this.ctx, $V([0, mouse.e(2)]), $V([this.canvasEl.width, mouse.e(2)]));
 
    line(this.ctx, $V([mouse.e(1), 0]), $V([mouse.e(1), this.canvasEl.height]));
 
    this.ctx.stroke();
 

	
 
    if (this.cursorPath) {
 
      this.ctx.strokeStyle = "#ff0303";
web/ascoltami/Light9AscoltamiTimeline.ts
Show inline comments
 
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 { 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";
 
@@ -28,25 +28,28 @@ export class Light9AscoltamiTimeline ext
 
    css`
 
      .timeRow {
 
        margin: 14px;
 
        position: relative;
 
      }
 
      #overview {
 
        height: 60px;
 
        height: 400px;
 
      }
 
      #zoomed {
 
        margin-top: 40px;
 
        height: 80px;
 
        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,
 
@@ -55,13 +58,13 @@ export class Light9AscoltamiTimeline ext
 
    song: null,
 
    wallStartTime: null,
 
  };
 
  @property() playerTime: number = 0;
 
  @state() zoom: Zoom;
 
  @state() overviewZoom: Zoom;
 
  @state() viewState: PlainViewState | null = null;
 
  @state() viewState: PlainerViewState | null = null;
 
  constructor() {
 
    super();
 
    getTopGraph().then((g) => {
 
      this.graph = g;
 
    });
 
    this.zoom = this.overviewZoom = { duration: null, t1: 0, t2: 1 };
 
@@ -84,21 +87,21 @@ export class Light9AscoltamiTimeline ext
 
    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,
 
      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]) },
 
      mouse: { pos: $V([0, 0]) },
 
    };
 
  }
 

	
 
  render() {
 
    const song = this.playerState?.song;
 
    if (!song) return html`(spectrogram)`;
web/light9-timeline-audio.ts
Show inline comments
 
@@ -33,12 +33,13 @@ export class Light9TimelineAudio extends
 
      <style>
 
        :host {
 
          display: block;
 
          /* shouldn't be seen, but black is correct for 'no
 
         audio'. Maybe loading stripes would be better */
 
          background: #202322;
 
          outline: 1px solid #333;
 
        }
 
        div {
 
          width: 100%;
 
          height: 100%;
 
          overflow: hidden;
 
        }
0 comments (0 inline, 0 general)