script.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. const bulbListEl = document.getElementById('bulbList');
  2. const addBulbBtn = document.getElementById('addBulb');
  3. const removeBulbBtn = document.getElementById('removeBulb');
  4. const controls = document.getElementById('controls');
  5. const noSelect = document.getElementById('noSelect');
  6. const onOffSwitch = document.getElementById('onOffSwitch');
  7. const brightness = document.getElementById('brightness');
  8. const temperature = document.getElementById('temperature');
  9. const brightnessVal = document.getElementById('brightnessVal');
  10. const temperatureVal = document.getElementById('temperatureVal');
  11. const light = document.getElementById('light');
  12. const visualization = document.getElementById('visualization');
  13. function kelvinToRGB(kelvin) {
  14. let temp = kelvin / 100;
  15. let red, green, blue;
  16. if (temp <= 66) {
  17. red = 255;
  18. } else {
  19. red = 329.698727446 * Math.pow(temp - 60, -0.1332047592);
  20. red = Math.min(Math.max(red, 0), 255);
  21. }
  22. if (temp <= 66) {
  23. green = 99.4708025861 * Math.log(temp) - 161.1195681661;
  24. green = Math.min(Math.max(green, 0), 255);
  25. } else {
  26. green = 288.1221695283 * Math.pow(temp - 60, -0.0755148492);
  27. green = Math.min(Math.max(green, 0), 255);
  28. }
  29. if (temp >= 66) {
  30. blue = 255;
  31. } else if (temp <= 19) {
  32. blue = 0;
  33. } else {
  34. blue = 138.5177312231 * Math.log(temp - 10) - 305.0447927307;
  35. blue = Math.min(Math.max(blue, 0), 255);
  36. }
  37. return {
  38. red_return: Math.round(red),
  39. green_return: Math.round(green),
  40. blue_return: Math.round(blue)
  41. };
  42. }
  43. let bulbs = [];
  44. let selectedBulb = null;
  45. function renderBulbList() {
  46. bulbListEl.innerHTML = '';
  47. bulbs.forEach((bulb, i) => {
  48. const div = document.createElement('div');
  49. div.className = 'bulb-item' + (selectedBulb === i ? ' selected' : '');
  50. div.textContent = `Bulb ${i + 1}`;
  51. div.onclick = () => selectBulb(i);
  52. bulbListEl.appendChild(div);
  53. });
  54. }
  55. function selectBulb(index) {
  56. selectedBulb = index;
  57. renderBulbList();
  58. updateUI();
  59. }
  60. function setControlsEnabled(enabled) {
  61. brightness.disabled = !enabled;
  62. temperature.disabled = !enabled;
  63. brightnessVal.style.opacity = enabled ? '1' : '0.5';
  64. temperatureVal.style.opacity = enabled ? '1' : '0.5';
  65. }
  66. function updateUI() {
  67. if (selectedBulb === null) {
  68. controls.style.display = 'none';
  69. noSelect.style.display = 'block';
  70. return;
  71. }
  72. const bulb = bulbs[selectedBulb];
  73. noSelect.style.display = 'none';
  74. controls.style.display = 'block';
  75. onOffSwitch.checked = bulb.on;
  76. brightness.value = bulb.brightness;
  77. temperature.value = bulb.temperature;
  78. brightnessVal.textContent = bulb.brightness;
  79. temperatureVal.textContent = bulb.temperature;
  80. setControlsEnabled(bulb.on);
  81. updateVisualization();
  82. }
  83. function clamp01(v) {
  84. return Math.max(0, Math.min(1, v));
  85. }
  86. function updateVisualization() {
  87. if (selectedBulb === null) {
  88. visualization.style.background = '#111';
  89. light.style.background = 'radial-gradient(circle, #000 0%, #000 100%)';
  90. light.style.boxShadow = 'none';
  91. return;
  92. }
  93. const bulb = bulbs[selectedBulb];
  94. if (!bulb.on) {
  95. visualization.style.background = '#111';
  96. light.style.background = 'radial-gradient(circle, #000 0%, #000 100%)';
  97. light.style.boxShadow = 'none';
  98. light.style.opacity = '1';
  99. return;
  100. }
  101. const b = clamp01(bulb.brightness / 100);
  102. const t = bulb.temperature;
  103. let color_conversion = kelvinToRGB(t);
  104. let color = `${color_conversion.red_return},${color_conversion.green_return},${color_conversion.blue_return}`;
  105. const faceAlpha = 0.25 + b * 0.75;
  106. const glowAlpha = 0.12 + b * 0.5;
  107. light.style.background = `radial-gradient(circle at 50% 35%, rgba(${color}, ${faceAlpha}) 0%, rgba(${color}, ${Math.max(0.06, faceAlpha * 0.3)}) 35%, rgba(0,0,0,0) 75%)`;
  108. const glowSize = 24 + b * 160;
  109. light.style.boxShadow = `0 0 ${glowSize}px rgba(${color}, ${glowAlpha}), 0 0 ${Math.round(glowSize/2)}px rgba(${color}, ${glowAlpha / 2})`;
  110. const roomGlowAlpha = Math.min(0.45, 0.06 + b * 0.25);
  111. visualization.style.background = `radial-gradient(circle at 50% 10%, rgba(${color}, ${roomGlowAlpha}) 0%, rgba(0,0,0,0) 45%), #111`;
  112. light.style.opacity = '1';
  113. }
  114. onOffSwitch.oninput = () => {
  115. if (selectedBulb === null) return;
  116. bulbs[selectedBulb].on = onOffSwitch.checked;
  117. setControlsEnabled(bulbs[selectedBulb].on);
  118. updateVisualization();
  119. };
  120. brightness.oninput = () => {
  121. if (selectedBulb === null) return;
  122. bulbs[selectedBulb].brightness = Number(brightness.value);
  123. brightnessVal.textContent = brightness.value;
  124. if (bulbs[selectedBulb].on) updateVisualization();
  125. };
  126. temperature.oninput = () => {
  127. if (selectedBulb === null) return;
  128. bulbs[selectedBulb].temperature = Number(temperature.value);
  129. temperatureVal.textContent = temperature.value;
  130. if (bulbs[selectedBulb].on) updateVisualization();
  131. };
  132. addBulbBtn.onclick = () => {
  133. bulbs.push({ on: false, brightness: 50, temperature: 3000 });
  134. renderBulbList();
  135. selectBulb(bulbs.length - 1);
  136. };
  137. removeBulbBtn.onclick = () => {
  138. if (selectedBulb === null) return;
  139. bulbs.splice(selectedBulb, 1);
  140. selectedBulb = null;
  141. renderBulbList();
  142. updateUI();
  143. };