mirror of
https://github.com/tiennm99/tiennm99bot.git
synced 2026-10-11 03:13:46 +00:00
fix(renderer): use consistent wheel label colors
This commit is contained in:
1 parent
7a0163ec01
commit
8de459b131
5 files changed
+39
-32
No files matched your search
@@ -9,7 +9,7 @@ import {
|
||||
getWheelRotationDegrees,
|
||||
rightPointerClipPath,
|
||||
} from './wheel-layout.js';
|
||||
import {getContrastingTextColor, getRadialLabelLayout} from './wheel-label-layout.js';
|
||||
import {getRadialLabelLayout} from './wheel-label-layout.js';
|
||||
import {getTheme} from './themes.js';
|
||||
|
||||
const baseFont =
|
||||
@@ -124,7 +124,7 @@ export const WheelComposition = (props) => {
|
||||
style={{
|
||||
alignItems: 'center',
|
||||
boxSizing: 'border-box',
|
||||
color: getContrastingTextColor(color),
|
||||
color: theme.text,
|
||||
display: 'flex',
|
||||
fontSize: label.fontSize,
|
||||
flexDirection: 'column',
|
||||
@@ -138,6 +138,7 @@ export const WheelComposition = (props) => {
|
||||
padding: `0 ${label.horizontalPadding}px`,
|
||||
position: 'absolute',
|
||||
textAlign: 'center',
|
||||
textShadow: `0 1px 0 ${theme.textHalo}, 0 -1px 0 ${theme.textHalo}, 1px 0 0 ${theme.textHalo}, -1px 0 0 ${theme.textHalo}`,
|
||||
top: label.y,
|
||||
transform: `translate(-50%, -50%) rotate(${label.rotation}deg)`,
|
||||
transformOrigin: '50% 50%',
|
||||
|
||||
@@ -21,7 +21,7 @@ export const themes = {
|
||||
text: '#1f2937',
|
||||
textHalo: 'rgba(255, 251, 235, 0.92)',
|
||||
winnerGlow: 'rgba(251, 146, 60, 0.5)',
|
||||
slices: ['#f43f5e', '#f59e0b', '#84cc16', '#06b6d4', '#8b5cf6', '#ec4899', '#22c55e', '#fb923c'],
|
||||
slices: ['#fb7185', '#f59e0b', '#84cc16', '#06b6d4', '#a78bfa', '#f472b6', '#22c55e', '#fb923c'],
|
||||
},
|
||||
mono: {
|
||||
background: '#f4f4f5',
|
||||
@@ -33,7 +33,7 @@ export const themes = {
|
||||
text: '#18181b',
|
||||
textHalo: 'rgba(250, 250, 250, 0.9)',
|
||||
winnerGlow: 'rgba(161, 161, 170, 0.45)',
|
||||
slices: ['#e4e4e7', '#a1a1aa', '#d4d4d8', '#71717a', '#f4f4f5', '#52525b'],
|
||||
slices: ['#e4e4e7', '#a1a1aa', '#d4d4d8', '#b8b8bf', '#f4f4f5', '#c4c4ca'],
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ export const estimateTextWidth = (text, fontSize) => {
|
||||
|
||||
return (widthUnits + 2) * fontSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string[]} units
|
||||
* @param {number} lineCount
|
||||
@@ -211,24 +210,3 @@ export const getRadialLabelLayout = ({center, radius, hubRadius, centerDegrees,
|
||||
lines,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} color
|
||||
* @returns {'#111827' | '#ffffff'}
|
||||
*/
|
||||
export const getContrastingTextColor = (color) => {
|
||||
const match = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/iu.exec(color);
|
||||
if (!match) {
|
||||
return '#111827';
|
||||
}
|
||||
|
||||
const redHex = match[1] ?? '00';
|
||||
const greenHex = match[2] ?? '00';
|
||||
const blueHex = match[3] ?? '00';
|
||||
const red = Number.parseInt(redHex, 16) / 255;
|
||||
const green = Number.parseInt(greenHex, 16) / 255;
|
||||
const blue = Number.parseInt(blueHex, 16) / 255;
|
||||
const luminance = 0.2126 * red + 0.7152 * green + 0.0722 * blue;
|
||||
|
||||
return luminance > 0.56 ? '#111827' : '#ffffff';
|
||||
};
|
||||
@@ -1,7 +1,6 @@
|
||||
import {describe, expect, test} from 'vitest';
|
||||
import {
|
||||
estimateTextWidth,
|
||||
getContrastingTextColor,
|
||||
getLabelFontSize,
|
||||
getLabelLines,
|
||||
getLabelTrack,
|
||||
@@ -242,9 +241,4 @@ describe('wheel label layout', () => {
|
||||
return !(firstCodeUnit >= 0xdc00 && firstCodeUnit <= 0xdfff) && !(lastCodeUnit >= 0xd800 && lastCodeUnit <= 0xdbff);
|
||||
})).toBe(true);
|
||||
});
|
||||
|
||||
test('uses contrast text colors for light and dark slices', () => {
|
||||
expect(getContrastingTextColor('#facc15')).toBe('#111827');
|
||||
expect(getContrastingTextColor('#7f1d1d')).toBe('#ffffff');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import {describe, expect, test} from 'vitest';
|
||||
import {themes} from '../src/remotion/themes.js';
|
||||
|
||||
/**
|
||||
* @param {string} color
|
||||
*/
|
||||
const getRelativeLuminance = (color) => {
|
||||
const channelHexValues = color.slice(1).match(/.{2}/gu) ?? [];
|
||||
const channels = channelHexValues
|
||||
.map((channel) => Number.parseInt(channel, 16) / 255)
|
||||
.map((channel) => (channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4));
|
||||
const [red = 0, green = 0, blue = 0] = channels;
|
||||
|
||||
return 0.2126 * red + 0.7152 * green + 0.0722 * blue;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} foreground
|
||||
* @param {string} background
|
||||
*/
|
||||
const getContrastRatio = (foreground, background) => {
|
||||
const luminances = [getRelativeLuminance(foreground), getRelativeLuminance(background)].sort(
|
||||
(left, right) => right - left,
|
||||
);
|
||||
const [lighter = 0, darker = 0] = luminances;
|
||||
|
||||
return (lighter + 0.05) / (darker + 0.05);
|
||||
};
|
||||
|
||||
describe('wheel themes', () => {
|
||||
test.each(Object.entries(themes))('%s uses one readable label color across every slice', (_name, theme) => {
|
||||
expect(theme.slices.every((slice) => getContrastRatio(theme.text, slice) >= 4.5)).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user