129 lines
3.7 KiB
JavaScript
129 lines
3.7 KiB
JavaScript
import { Conductor } from "./conductor.js";
|
|
|
|
export class Renderer {
|
|
timeIndicator;
|
|
currStaveNumber;
|
|
numStaves;
|
|
sheetWindow;
|
|
canvases = [];
|
|
iconCache = [];
|
|
iconScale = 0.20;
|
|
|
|
constructor() {
|
|
this.numStaves = 6;
|
|
this.currStaveNumber = 1;
|
|
|
|
this.timeIndicator = document.getElementById("time-indicator");
|
|
this.sheetWindow = document.getElementById("music-window");
|
|
|
|
window.addEventListener("resize", () => {
|
|
this.redrawIcons();
|
|
});
|
|
|
|
this.timeIndicator.addEventListener("animationiteration", () => {
|
|
this.currStaveNumber++;
|
|
if (this.currStaveNumber > this.numStaves) {
|
|
this.cleanUpAndRestart();
|
|
}
|
|
});
|
|
|
|
for (let i = 1; i <= this.numStaves; i++) {
|
|
const staveWrapper = document.createElement("div");
|
|
staveWrapper.classList.add("stave-wrapper");
|
|
staveWrapper.setAttribute("id", `stave-wrapper-${i}`);
|
|
staveWrapper.style.position = "relative";
|
|
|
|
const staveObject = document.createElement("object");
|
|
staveObject.type = "image/svg+xml";
|
|
staveObject.data = "assets/svg/stave.svg";
|
|
staveObject.className = "stave-svg"; // Fixed className
|
|
|
|
const canvas = document.createElement("canvas");
|
|
canvas.id = `canvas-${i}`;
|
|
canvas.className = "event-canvas";
|
|
|
|
const ctx = canvas.getContext("2d");
|
|
this.canvases.push({ canvas, ctx });
|
|
|
|
staveWrapper.appendChild(staveObject);
|
|
staveWrapper.appendChild(canvas);
|
|
this.sheetWindow.appendChild(staveWrapper);
|
|
|
|
// Your exact sizing method + minimal DPR adjustment
|
|
requestAnimationFrame(() => {
|
|
const dpr = window.devicePixelRatio || 1;
|
|
|
|
// Keep your offset measurements
|
|
const displayWidth = canvas.offsetWidth;
|
|
const displayHeight = canvas.offsetHeight;
|
|
|
|
// Apply to actual canvas buffer
|
|
canvas.width = Math.round(displayWidth * dpr);
|
|
canvas.height = Math.round(displayHeight * dpr);
|
|
|
|
// Maintain your display size
|
|
canvas.style.width = `${displayWidth}px`;
|
|
canvas.style.height = `${displayHeight}px`;
|
|
|
|
// Scale context to compensate
|
|
ctx.scale(dpr , dpr);
|
|
});
|
|
}
|
|
}
|
|
|
|
async placeIcon(instrument) {
|
|
if (this.currStaveNumber > this.numStaves) {
|
|
this.currStaveNumber = 1;
|
|
this.iconCache.length = 0;
|
|
}
|
|
|
|
const rect = this.timeIndicator.getBoundingClientRect();
|
|
const sheetLeft = this.sheetWindow.getBoundingClientRect().left;
|
|
const xPosition = rect.left + window.scrollX - sheetLeft;
|
|
|
|
const canvasEntry = this.canvases[this.currStaveNumber - 1];
|
|
const canvas = canvasEntry.canvas;
|
|
const ctx = canvasEntry.ctx;
|
|
|
|
const yPercent = parseFloat(instrument.yPos);
|
|
const y = (yPercent / 100) * canvas.height;
|
|
|
|
const width = instrument.width * this.iconScale;
|
|
const height = instrument.height * this.iconScale;
|
|
|
|
ctx.drawImage(instrument.image, xPosition, y, width, height);
|
|
|
|
this.iconCache.push({
|
|
image: instrument.image,
|
|
x: xPosition,
|
|
y,
|
|
width,
|
|
height,
|
|
stave: this.currStaveNumber,
|
|
});
|
|
}
|
|
|
|
redrawIcons() {
|
|
this.canvases.forEach(({ ctx, canvas }) => {
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
});
|
|
|
|
this.iconCache.forEach(({ image, x, y, width, height, stave }) => {
|
|
const ctx = this.canvases[stave - 1].ctx;
|
|
ctx.drawImage(image, x, y, width, height);
|
|
});
|
|
}
|
|
|
|
cleanUpAndRestart(reload = false) {
|
|
this.iconCache = [];
|
|
this.currStaveNumber = 1;
|
|
|
|
this.canvases.forEach(({ ctx, canvas }) => {
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
});
|
|
|
|
Conductor.setTitle();
|
|
if (reload) location.reload();
|
|
}
|
|
}
|