From 9ba8adbd8558425d59f8bbc3ae413f23cbf055ac Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Tue, 13 Feb 2024 11:29:56 +0100 Subject: [PATCH] feat: use a WCAG algo to define contrast colour I've decided for a basic home made util, because: - I'm not sure color is still maintained - colorjs.io sounds very cool and maintained, but is 105k - there is no custom bundle yet - it uses proper modules, but for just the contrast util we need to pull all the class logic, and it's a lot --- umap/static/umap/js/umap.core.js | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/umap/static/umap/js/umap.core.js b/umap/static/umap/js/umap.core.js index ba6a7118..55388cbb 100644 --- a/umap/static/umap/js/umap.core.js +++ b/umap/static/umap/js/umap.core.js @@ -396,10 +396,28 @@ L.DomUtil.after = (target, el) => { return el } +// From https://gist.github.com/Accudio/b9cb16e0e3df858cef0d31e38f1fe46f +// convert colour in range 0-255 to the modifier used within luminance calculation +L.DomUtil.colourMod = (colour) => { + const sRGB = colour / 255 + let mod = Math.pow((sRGB + 0.055) / 1.055, 2.4) + if (sRGB < 0.03928) mod = sRGB / 12.92 + return mod +} L.DomUtil.RGBRegex = /rgb *\( *([0-9]{1,3}) *, *([0-9]{1,3}) *, *([0-9]{1,3}) *\)/ L.DomUtil.TextColorFromBackgroundColor = (el, bgcolor) => { return L.DomUtil.contrastedColor(el, bgcolor) ? '#ffffff' : '#000000' } +L.DomUtil.contrastWCAG21 = (rgb) => { + const [r, g, b] = rgb + // luminance of inputted colour + const lum = 0.2126 * L.DomUtil.colourMod(r) + 0.7152 * L.DomUtil.colourMod(g) + 0.0722 * L.DomUtil.colourMod(b) + // white has a luminance of 1 + const whiteLum = 1 + const contrast = (whiteLum + 0.05) / (lum + 0.05) + return contrast > 3 ? 1 : 0 +} + const _CACHE_CONSTRAST = {} L.DomUtil.contrastedColor = (el, bgcolor) => { // Return 0 for black and 1 for white @@ -409,9 +427,8 @@ L.DomUtil.contrastedColor = (el, bgcolor) => { let rgb = window.getComputedStyle(el).getPropertyValue('background-color') rgb = L.DomUtil.RGBRegex.exec(rgb) if (!rgb || rgb.length !== 4) return out - rgb = parseInt(rgb[1], 10) + parseInt(rgb[2], 10) + parseInt(rgb[3], 10) - const threshold = 140 - if (rgb < threshold * 3) out = 1 + rgb = [parseInt(rgb[1], 10), parseInt(rgb[2], 10), parseInt(rgb[3], 10)] + out = L.DomUtil.contrastWCAG21(rgb) if (bgcolor) _CACHE_CONSTRAST[bgcolor] = out return out }