museaikit
Version:
A powerful music-focused AI toolkit
106 lines • 3.95 kB
JavaScript
import { BaseVisualizer } from './base_visualizer';
export class BaseSVGVisualizer extends BaseVisualizer {
svg;
drawn;
constructor(sequence, config = {}) {
super(sequence, config);
this.drawn = false;
}
redraw(activeNote, scrollIntoView) {
if (!this.drawn) {
this.draw();
}
if (!activeNote) {
return null;
}
this.unfillActiveRect(this.svg);
let activeNotePosition;
for (let i = 0; i < this.noteSequence.notes.length; i++) {
const note = this.noteSequence.notes[i];
const isActive = activeNote && this.isPaintingActiveNote(note, activeNote);
if (!isActive) {
continue;
}
const el = this.svg.querySelector(`rect[data-index="${i}"]`);
this.fillActiveRect(el, note);
if (note === activeNote) {
activeNotePosition = parseFloat(el.getAttribute('x'));
}
}
this.scrollIntoViewIfNeeded(scrollIntoView, activeNotePosition);
return activeNotePosition;
}
fillActiveRect(el, note) {
el.setAttribute('fill', this.getNoteFillColor(note, true));
el.classList.add('active');
}
unfillActiveRect(svg) {
const els = svg.querySelectorAll('rect.active');
for (let i = 0; i < els.length; ++i) {
const el = els[i];
const fill = this.getNoteFillColor(this.noteSequence.notes[parseInt(el.getAttribute('data-index'), 10)], false);
el.setAttribute('fill', fill);
el.classList.remove('active');
}
}
draw() {
for (let i = 0; i < this.noteSequence.notes.length; i++) {
const note = this.noteSequence.notes[i];
const size = this.getNotePosition(note, i);
const fill = this.getNoteFillColor(note, false);
const dataAttributes = [
['index', i],
['instrument', note.instrument],
['program', note.program],
['isDrum', note.isDrum === true],
['pitch', note.pitch],
];
const cssProperties = [
['--midi-velocity',
String(note.velocity !== undefined ? note.velocity : 127)]
];
this.drawNote(size.x, size.y, size.w, size.h, fill, dataAttributes, cssProperties);
}
this.drawn = true;
}
getNoteFillColor(note, isActive) {
const opacityBaseline = 0.2;
const opacity = note.velocity ? note.velocity / 100 + opacityBaseline : 1;
const fill = `rgba(${isActive ? this.config.activeNoteRGB : this.config.noteRGB},
${opacity})`;
return fill;
}
drawNote(x, y, w, h, fill, dataAttributes, cssProperties) {
if (!this.svg) {
return;
}
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
rect.classList.add('note');
rect.setAttribute('fill', fill);
rect.setAttribute('x', `${Math.round(x)}`);
rect.setAttribute('y', `${Math.round(y)}`);
rect.setAttribute('width', `${Math.round(w)}`);
rect.setAttribute('height', `${Math.round(h)}`);
dataAttributes.forEach(([key, value]) => {
if (value !== undefined) {
rect.dataset[key] = `${value}`;
}
});
cssProperties.forEach(([key, value]) => {
rect.style.setProperty(key, value);
});
this.svg.appendChild(rect);
}
clear() {
if (this.svg) {
this.svg.innerHTML = '';
}
this.drawn = false;
}
clearActiveNotes() {
if (this.svg) {
this.unfillActiveRect(this.svg);
}
}
}
//# sourceMappingURL=base_svg_visualizer.js.map