Add dynamic text color adjustment based on background brightness
Automatically adjusts text color for optimal readability: - Bright backgrounds: Text switches to dark color (#1a1a1a) - Dark backgrounds: Text remains white (#ffffff) - Uses luminance formula (0.299×R + 0.587×G + 0.114×B) for accurate brightness detection - Analyzes images using canvas to sample 100x100 pixels - Smooth color transitions (0.5s) between background changes - Adjusts text shadows for better contrast in each mode - Event time color adapts (#0066cc for light, #4a9eff for dark) Technical implementation: - Added calculateImageBrightness() function in app.js - Modified updateBackground() to analyze and apply appropriate CSS class - Added .light-bg and .dark-bg CSS classes for text color themes - Brightness threshold set at 140 (out of 255) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -212,6 +212,56 @@ async function updateCalendar() {
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate brightness of an image
|
||||
function calculateImageBrightness(imageSrc, callback) {
|
||||
const img = new Image();
|
||||
img.crossOrigin = 'Anonymous';
|
||||
|
||||
img.onload = () => {
|
||||
// Create a canvas to analyze the image
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
// Use a smaller size for faster processing
|
||||
canvas.width = 100;
|
||||
canvas.height = 100;
|
||||
|
||||
// Draw the image scaled down
|
||||
ctx.drawImage(img, 0, 0, 100, 100);
|
||||
|
||||
// Get image data
|
||||
const imageData = ctx.getImageData(0, 0, 100, 100);
|
||||
const data = imageData.data;
|
||||
|
||||
// Calculate average brightness
|
||||
let totalBrightness = 0;
|
||||
const pixelCount = data.length / 4;
|
||||
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
const r = data[i];
|
||||
const g = data[i + 1];
|
||||
const b = data[i + 2];
|
||||
|
||||
// Calculate perceived brightness (using luminance formula)
|
||||
const brightness = (0.299 * r + 0.587 * g + 0.114 * b);
|
||||
totalBrightness += brightness;
|
||||
}
|
||||
|
||||
const avgBrightness = totalBrightness / pixelCount;
|
||||
|
||||
// Return brightness value (0-255)
|
||||
callback(avgBrightness);
|
||||
};
|
||||
|
||||
img.onerror = () => {
|
||||
console.error('Error loading image for brightness analysis');
|
||||
// Default to dark background if error
|
||||
callback(100);
|
||||
};
|
||||
|
||||
img.src = imageSrc;
|
||||
}
|
||||
|
||||
// Update background image
|
||||
async function updateBackground() {
|
||||
try {
|
||||
@@ -226,11 +276,28 @@ async function updateBackground() {
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
backgroundElement.style.backgroundImage = `url('${data.image}')`;
|
||||
|
||||
// Analyze brightness and adjust text color
|
||||
calculateImageBrightness(data.image, (brightness) => {
|
||||
// Threshold: 128 is middle brightness
|
||||
// If brightness > 140, use dark text (light background)
|
||||
// If brightness <= 140, use white text (dark background)
|
||||
if (brightness > 140) {
|
||||
document.body.classList.remove('dark-bg');
|
||||
document.body.classList.add('light-bg');
|
||||
} else {
|
||||
document.body.classList.remove('light-bg');
|
||||
document.body.classList.add('dark-bg');
|
||||
}
|
||||
});
|
||||
};
|
||||
img.src = data.image;
|
||||
} else if (data.color) {
|
||||
backgroundElement.style.backgroundColor = data.color;
|
||||
backgroundElement.style.backgroundImage = 'none';
|
||||
// Assume solid colors are dark
|
||||
document.body.classList.remove('light-bg');
|
||||
document.body.classList.add('dark-bg');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user