Add global brightness control feature with socket handling and UI updates

This commit is contained in:
2025-07-07 10:05:14 +03:00
parent 09d8871ac3
commit d0f34846f8
3 changed files with 201 additions and 95 deletions

View File

@@ -75,7 +75,7 @@
top: 0;
left: 0;
width: 100%;
height: 1000px; /* 10 digits * 100px each */
height: 1200px; /* 10 digits * 120px each (matches default wheel height) */
transition: transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
display: flex;
flex-direction: column;
@@ -83,7 +83,7 @@
.digit {
width: 100%;
height: 100px;
height: 120px;
display: flex;
justify-content: center;
align-items: center;
@@ -143,64 +143,13 @@
z-index: 1;
}
.mechanical-sound::before {
content: '';
position: absolute;
top: 50%;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, transparent, #ffffff, transparent);
opacity: 0;
transition: opacity 0.3s;
}
.digit-wheel.animating .mechanical-sound::before {
opacity: 1;
}
/* Glitch effect for mechanical feel */
.digit-wheel.animating .digit.active {
animation: glitch 0.1s ease-in-out;
}
@keyframes glitch {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-1px); }
75% { transform: translateX(1px); }
}
/* Mechanical click sound simulation */
.click-indicator {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 4px;
height: 4px;
background: #ffffff;
border-radius: 50%;
opacity: 0;
z-index: 3;
}
.digit-wheel.animating .click-indicator {
animation: click 0.8s ease-in-out;
}
@keyframes click {
0% { opacity: 0; transform: translate(-50%, -50%) scale(0); }
50% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
100% { opacity: 0; transform: translate(-50%, -50%) scale(2); }
}
/* Removed visual effects that caused white lines during animation */
</style>
</head>
<body>
<div id="status" class="status disconnected">Disconnected</div>
<div class="digit-wheel" id="digit0" data-position="0" style="left: 50px; top: 200px;">
<div class="mechanical-sound"></div>
<div class="click-indicator"></div>
<div class="digit-strip" data-current="0">
<div class="digit">0</div>
<div class="digit">1</div>
@@ -216,8 +165,6 @@
</div>
<div class="digit-wheel" id="digit1" data-position="1" style="left: 150px; top: 200px;">
<div class="mechanical-sound"></div>
<div class="click-indicator"></div>
<div class="digit-strip" data-current="0">
<div class="digit">0</div>
<div class="digit">1</div>
@@ -233,8 +180,6 @@
</div>
<div class="digit-wheel" id="digit2" data-position="2" style="left: 250px; top: 200px;">
<div class="mechanical-sound"></div>
<div class="click-indicator"></div>
<div class="digit-strip" data-current="0">
<div class="digit">0</div>
<div class="digit">1</div>
@@ -250,8 +195,6 @@
</div>
<div class="digit-wheel" id="digit3" data-position="3" style="left: 350px; top: 200px;">
<div class="mechanical-sound"></div>
<div class="click-indicator"></div>
<div class="digit-strip" data-current="0">
<div class="digit">0</div>
<div class="digit">1</div>
@@ -267,8 +210,6 @@
</div>
<div class="digit-wheel" id="digit4" data-position="4" style="left: 450px; top: 200px;">
<div class="mechanical-sound"></div>
<div class="click-indicator"></div>
<div class="digit-strip" data-current="0">
<div class="digit">0</div>
<div class="digit">1</div>
@@ -284,8 +225,6 @@
</div>
<div class="digit-wheel" id="digit5" data-position="5" style="left: 550px; top: 200px;">
<div class="mechanical-sound"></div>
<div class="click-indicator"></div>
<div class="digit-strip" data-current="0">
<div class="digit">0</div>
<div class="digit">1</div>
@@ -319,6 +258,9 @@
// Animation speed (default value)
let currentAnimationSpeed = 0.5;
// Brightness (default value)
let currentBrightness = 100;
// Connection status
socket.on('connect', function() {
@@ -372,6 +314,12 @@
updateAnimationSpeed(data.speed || data);
});
// Handle brightness updates from controller
socket.on('brightness_update', function(data) {
console.log('Received brightness update:', data);
updateBrightness(data.brightness || data);
});
// Handle general events (for backward compatibility)
socket.on('receive_event', function(data) {
console.log('Received event:', data);
@@ -390,6 +338,9 @@
if (data.type === 'animation_speed' || data.speed) {
updateAnimationSpeed(data.speed || data);
}
if (data.type === 'brightness' || data.brightness) {
updateBrightness(data.brightness || data);
}
});
function updateCounter(values) {
@@ -450,6 +401,7 @@
const currentValue = parseInt(strip.getAttribute('data-current') || '0');
const targetY = -(currentValue * height);
strip.style.transform = `translateY(${targetY}px)`;
console.log(`Recalculated digit strip ${index} position to ${targetY}px for value ${currentValue}`);
});
// Update individual digit heights and widths
@@ -473,6 +425,21 @@
});
}
function updateBrightness(brightness) {
console.log('Updating brightness to:', brightness);
currentBrightness = brightness;
// Calculate brightness filter value (0-1 range)
const brightnessFilter = brightness / 100;
// Update all digit wheels with new brightness
const digitWheels = document.querySelectorAll('.digit-wheel');
digitWheels.forEach((wheel, index) => {
wheel.style.filter = `brightness(${brightnessFilter})`;
console.log(`Updated digit wheel ${index} brightness to ${brightness}% (filter: ${brightnessFilter})`);
});
}
function animateDigitWheel(position, fromValue, toValue) {
const wheel = digitWheels[position];
const strip = wheel.querySelector('.digit-strip');
@@ -485,6 +452,8 @@
// Calculate the target position using current wheel height
const targetY = -(toValue * wheelHeight);
console.log(`Animating digit ${position} from ${fromValue} to ${toValue}, targetY: ${targetY}, wheelHeight: ${wheelHeight}`);
// Add animation class
wheel.classList.add('animating');
@@ -498,9 +467,14 @@
digit.classList.toggle('active', index === toValue);
});
// Remove animation class after animation completes
// Remove animation class after animation completes and ensure proper positioning
setTimeout(() => {
wheel.classList.remove('animating');
// Double-check the position is correct after animation
const finalTargetY = -(toValue * wheelHeight);
strip.style.transform = `translateY(${finalTargetY}px)`;
console.log(`Final position check for digit ${position}: ${finalTargetY}px`);
}, currentAnimationSpeed * 1000);
}
@@ -543,36 +517,7 @@
socket.emit('viewport_update', viewportData);
}
// Add some mechanical sound simulation
function playMechanicalSound() {
// Create a simple mechanical click sound using Web Audio API
try {
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.frequency.setValueAtTime(800, audioContext.currentTime);
oscillator.frequency.exponentialRampToValueAtTime(400, audioContext.currentTime + 0.1);
gainNode.gain.setValueAtTime(0.1, audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.1);
oscillator.start(audioContext.currentTime);
oscillator.stop(audioContext.currentTime + 0.1);
} catch (e) {
console.log('Audio not supported');
}
}
// Play sound when digits animate
document.addEventListener('animationstart', function(e) {
if (e.target.classList.contains('digit-wheel')) {
playMechanicalSound();
}
});
// Removed mechanical sound simulation to eliminate white lines during animation
</script>
</body>
</html>

View File

@@ -643,6 +643,102 @@
border-bottom: 1px solid #333;
}
.brightness-controls {
background: rgba(0, 0, 0, 0.5);
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
border: 1px solid #00ff00;
}
.brightness-controls h3 {
color: #00ff00;
text-align: center;
margin-bottom: 15px;
}
.brightness-group {
display: flex;
align-items: center;
gap: 15px;
justify-content: center;
margin-bottom: 15px;
}
.brightness-label {
font-weight: bold;
color: #00ff00;
min-width: 120px;
}
.brightness-slider {
flex: 1;
max-width: 300px;
height: 6px;
background: rgba(255, 255, 255, 0.2);
border-radius: 3px;
outline: none;
-webkit-appearance: none;
}
.brightness-slider::-webkit-slider-thumb {
-webkit-appearance: none;
width: 16px;
height: 16px;
background: #00ff00;
border-radius: 50%;
cursor: pointer;
}
.brightness-slider::-moz-range-thumb {
width: 16px;
height: 16px;
background: #00ff00;
border-radius: 50%;
cursor: pointer;
border: none;
}
.brightness-value {
min-width: 80px;
text-align: center;
font-family: monospace;
color: #00ff00;
font-weight: bold;
}
.brightness-preview {
display: inline-block;
padding: 10px;
background: rgba(0, 0, 0, 0.8);
border: 1px solid #00ff00;
border-radius: 5px;
margin-left: 15px;
text-align: center;
}
.brightness-preview-box {
width: 40px;
height: 60px;
background: linear-gradient(145deg, #2a2a2a, #1a1a1a);
border: 1px solid #444;
border-radius: 5px;
display: inline-block;
position: relative;
overflow: hidden;
}
.brightness-preview-digit {
width: 100%;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
font-size: 20px;
background: linear-gradient(145deg, #1a1a1a, #0a0a0a);
}
.counter-preview {
text-align: center;
margin-bottom: 20px;
@@ -730,6 +826,24 @@
</div>
</div>
<div class="brightness-controls">
<h3>Global Brightness Control</h3>
<div class="brightness-group">
<div class="brightness-label">Brightness:</div>
<input type="range" class="brightness-slider" id="globalBrightness" min="0" max="100" value="100" step="5">
<span class="brightness-value" id="globalBrightnessValue">100%</span>
<div class="brightness-preview">
<div class="brightness-preview-box" id="brightnessPreviewBox">
<div class="brightness-preview-digit" id="brightnessPreviewDigit">8</div>
</div>
</div>
</div>
<div style="text-align: center;">
<button class="btn btn-primary" onclick="updateGlobalBrightness()">Update All Wheels</button>
<button class="btn btn-secondary" onclick="resetGlobalBrightness()">Reset to Default</button>
</div>
</div>
<div class="wheel-size-controls">
<h3>Digit Wheel Size</h3>
<div class="wheel-size-group">
@@ -963,6 +1077,9 @@
// Animation speed (default value)
let currentAnimationSpeed = 0.5;
// Brightness (default value)
let currentBrightness = 100;
// Connection status
socket.on('connect', function() {
@@ -1071,6 +1188,21 @@
speedPreviewStrip.style.transition = `transform ${newSpeed}s ease`;
});
// Add event listener to brightness slider
const brightnessSlider = document.getElementById('globalBrightness');
const brightnessValue = document.getElementById('globalBrightnessValue');
const brightnessPreviewBox = document.getElementById('brightnessPreviewBox');
brightnessSlider.addEventListener('input', function() {
const newBrightness = parseInt(this.value);
currentBrightness = newBrightness;
brightnessValue.textContent = newBrightness + '%';
// Update preview with brightness filter
const brightnessFilter = newBrightness / 100;
brightnessPreviewBox.style.filter = `brightness(${brightnessFilter})`;
});
function updateCounter() {
const counterData = {
type: 'counter_update',
@@ -1300,6 +1432,27 @@
}, (currentAnimationSpeed * 1000) + 200);
}
function updateGlobalBrightness() {
const brightnessData = {
type: 'brightness_update',
brightness: currentBrightness,
timestamp: new Date().toISOString()
};
console.log('Sending brightness update:', brightnessData);
socket.emit('brightness_update', brightnessData);
addSentEvent(brightnessData);
}
function resetGlobalBrightness() {
const defaultBrightness = 100;
brightnessSlider.value = defaultBrightness;
currentBrightness = defaultBrightness;
brightnessValue.textContent = defaultBrightness + '%';
brightnessPreviewBox.style.filter = 'brightness(1)';
updateGlobalBrightness();
}
function incrementDigit(index) {
let currentValue = currentValues[index];
currentValue = (currentValue + 1) % 10; // Wrap around from 9 to 0