Use a dichotomy to find a color with a good contrast ratio

It helps to reduce the number of iterations so it makes the algorithm
slightly faster in general.
This commit is contained in:
Calixte Denizet 2025-09-13 15:44:56 +02:00
parent d77f89026f
commit 634bef5fb4
2 changed files with 26 additions and 9 deletions

View File

@ -16,7 +16,6 @@
import { import {
BaseException, BaseException,
FeatureTest, FeatureTest,
MathClamp,
shadow, shadow,
Util, Util,
warn, warn,
@ -931,18 +930,36 @@ function findContrastColor(baseColor, fixedColor) {
// Use the contrast ratio requirements from WCAG 2.1. // Use the contrast ratio requirements from WCAG 2.1.
// https://www.w3.org/TR/WCAG21/#contrast-minimum // https://www.w3.org/TR/WCAG21/#contrast-minimum
// https://www.w3.org/TR/WCAG21/#contrast-enhanced // https://www.w3.org/TR/WCAG21/#contrast-enhanced
const minContrast = isFixedColorDark ? 7 : 4.5; const minContrast = isFixedColorDark ? 12 : 4.5;
baseHSL[2] = isFixedColorDark baseHSL[2] = isFixedColorDark
? Math.sqrt(baseHSL[2]) ? Math.sqrt(baseHSL[2])
: 1 - Math.sqrt(1 - baseHSL[2]); : 1 - Math.sqrt(1 - baseHSL[2]);
const increment = isFixedColorDark ? 0.01 : -0.01;
let contrast = contrastRatio(baseHSL, fixedHSL, output); if (contrastRatio(baseHSL, fixedHSL, output) < minContrast) {
while (baseHSL[2] >= 0 && baseHSL[2] <= 1 && contrast < minContrast) { let start, end;
baseHSL[2] += increment; if (isFixedColorDark) {
contrast = contrastRatio(baseHSL, fixedHSL, output); start = baseHSL[2];
end = 1;
} else {
start = 0;
end = baseHSL[2];
}
const PRECISION = 0.005;
while (end - start > PRECISION) {
const mid = (baseHSL[2] = (start + end) / 2);
if (
isFixedColorDark ===
contrastRatio(baseHSL, fixedHSL, output) < minContrast
) {
start = mid;
} else {
end = mid;
}
}
baseHSL[2] = isFixedColorDark ? end : start;
} }
baseHSL[2] = MathClamp(baseHSL[2], 0, 1);
HSLToRGB(baseHSL, output); HSLToRGB(baseHSL, output);
cachedValue = Util.makeHexColor( cachedValue = Util.makeHexColor(
Math.round(output[0] * 255), Math.round(output[0] * 255),

View File

@ -307,7 +307,7 @@ describe("display_utils", function () {
describe("findContrastColor", function () { describe("findContrastColor", function () {
it("Check that the lightness is changed correctly", function () { it("Check that the lightness is changed correctly", function () {
expect(findContrastColor([210, 98, 76], [197, 113, 89])).toEqual( expect(findContrastColor([210, 98, 76], [197, 113, 89])).toEqual(
"#240d09" "#260e09"
); );
}); });
}); });