periodic_table / SpectrumDisplayComponent.js
AK51's picture
Upload 18 files
ab59545 verified
import { getSpectrumColor } from './wavelengthUtils.js';
export class SpectrumDisplayComponent {
constructor(dataManager) {
this.dataManager = dataManager;
this.infoPanel = document.getElementById('info-panel');
this.elementName = document.getElementById('element-name');
this.elementDetails = document.getElementById('element-details');
this.spectrumContainer = document.getElementById('spectrum-container');
}
showSpectrum(symbol) {
const elementData = this.dataManager.getElementData(symbol);
if (!elementData) {
this.showNoData(symbol);
return;
}
// Update element info
this.elementName.textContent = elementData.name;
this.elementDetails.textContent = `Symbol: ${elementData.symbol} | Atomic Number: ${elementData.atomicNumber}`;
// Create spectrum visualization
this.createSpectralLines(elementData.spectralLines);
// Show panel
this.infoPanel.classList.remove('hidden');
}
hideSpectrum() {
this.infoPanel.classList.add('hidden');
this.spectrumContainer.innerHTML = '';
}
createSpectralLines(lines) {
this.spectrumContainer.innerHTML = '';
if (!lines || lines.length === 0) {
this.spectrumContainer.innerHTML = '<p>No spectral data available</p>';
return;
}
// Sort by intensity and limit to top 20
const sortedLines = [...lines].sort((a, b) => (b.intensity || 0) - (a.intensity || 0));
const displayLines = sortedLines.slice(0, 20);
// Create canvas for spectrum
const canvas = document.createElement('canvas');
canvas.width = 360;
canvas.height = 200;
canvas.style.width = '100%';
canvas.style.border = '1px solid rgba(255, 255, 255, 0.2)';
canvas.style.borderRadius = '5px';
const ctx = canvas.getContext('2d');
// Draw background
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Find wavelength range
const wavelengths = displayLines.map(l => l.wavelength);
const minWave = Math.min(...wavelengths, 380);
const maxWave = Math.max(...wavelengths, 750);
const range = maxWave - minWave;
// Draw wavelength scale
ctx.fillStyle = '#666';
ctx.font = '10px Arial';
ctx.textAlign = 'center';
for (let w = Math.ceil(minWave / 50) * 50; w <= maxWave; w += 50) {
const x = ((w - minWave) / range) * (canvas.width - 40) + 20;
ctx.fillRect(x, canvas.height - 20, 1, 10);
ctx.fillText(w + 'nm', x, canvas.height - 5);
}
// Draw spectral lines
displayLines.forEach(line => {
const { color, opacity } = getSpectrumColor(line.wavelength);
const x = ((line.wavelength - minWave) / range) * (canvas.width - 40) + 20;
const height = (line.intensity || 0.5) * 140;
ctx.fillStyle = `rgba(${Math.floor(color.r * 255)}, ${Math.floor(color.g * 255)}, ${Math.floor(color.b * 255)}, ${opacity})`;
ctx.fillRect(x - 2, canvas.height - 30 - height, 4, height);
// Draw wavelength label for prominent lines
if (line.intensity > 0.5) {
ctx.fillStyle = '#fff';
ctx.font = '9px Arial';
ctx.save();
ctx.translate(x, canvas.height - 35 - height);
ctx.rotate(-Math.PI / 2);
ctx.fillText(line.wavelength.toFixed(1), 0, 0);
ctx.restore();
}
});
this.spectrumContainer.appendChild(canvas);
// Add line details
const detailsDiv = document.createElement('div');
detailsDiv.style.marginTop = '10px';
detailsDiv.style.fontSize = '12px';
detailsDiv.style.maxHeight = '200px';
detailsDiv.style.overflowY = 'auto';
detailsDiv.innerHTML = '<h3 style="margin-bottom: 10px;">Spectral Lines:</h3>';
displayLines.forEach(line => {
const lineDiv = document.createElement('div');
lineDiv.style.marginBottom = '5px';
lineDiv.style.padding = '5px';
lineDiv.style.background = 'rgba(255, 255, 255, 0.05)';
lineDiv.style.borderRadius = '3px';
const { color } = getSpectrumColor(line.wavelength);
const colorBox = `<span style="display: inline-block; width: 12px; height: 12px; background: rgb(${Math.floor(color.r * 255)}, ${Math.floor(color.g * 255)}, ${Math.floor(color.b * 255)}); border: 1px solid #fff; margin-right: 5px;"></span>`;
lineDiv.innerHTML = `${colorBox}${line.wavelength.toFixed(1)} nm (Intensity: ${(line.intensity || 0).toFixed(2)})${line.transition ? ' - ' + line.transition : ''}`;
detailsDiv.appendChild(lineDiv);
});
this.spectrumContainer.appendChild(detailsDiv);
}
showNoData(symbol) {
this.elementName.textContent = symbol;
this.elementDetails.textContent = 'Element information';
this.spectrumContainer.innerHTML = '<p>Spectral data not available for this element</p>';
this.infoPanel.classList.remove('hidden');
}
}