Automagically change svg icon color according to background color

This commit is contained in:
Yohan Boniface 2023-10-30 18:14:41 +01:00
parent b6aa201397
commit b10838c5ba
3 changed files with 32 additions and 24 deletions

View file

@ -363,21 +363,21 @@ L.DomUtil.after = (target, el) => {
}
L.DomUtil.RGBRegex = /rgb *\( *([0-9]{1,3}) *, *([0-9]{1,3}) *, *([0-9]{1,3}) *\)/
L.DomUtil.TextColorFromBackgroundColor = (el) => {
let out = '#000000'
if (!window.getComputedStyle) {
return out
}
return L.DomUtil.contrastedColor(el) ? '#ffffff' : '#000000'
}
const _CACHE_CONSTRAST = {}
L.DomUtil.contrastedColor = (el, bgcolor) => {
// Return 0 for black and 1 for white
// bgcolor is a human color, it can be a any keyword (purple…)
if (typeof _CACHE_CONSTRAST[bgcolor] !== 'undefined') return _CACHE_CONSTRAST[bgcolor]
let out = 0
let rgb = window.getComputedStyle(el).getPropertyValue('background-color')
rgb = L.DomUtil.RGBRegex.exec(rgb)
if (!rgb || rgb.length !== 4) {
return out
}
if (!rgb || rgb.length !== 4) return out
rgb = parseInt(rgb[1], 10) + parseInt(rgb[2], 10) + parseInt(rgb[3], 10)
if (rgb < (255 * 3) / 2) {
out = '#ffffff'
}
if (rgb < (255 * 3) / 2) out = 1
if (bgcolor) _CACHE_CONSTRAST[bgcolor] = out
return out
}
L.DomEvent.once = (el, types, fn, context) => {

View file

@ -608,6 +608,8 @@ L.U.Marker = L.Marker.extend({
_initIcon: function () {
this.options.icon = this.getIcon()
L.Marker.prototype._initIcon.call(this)
// Allow to run code when icon is actually part of the DOM
this.options.icon.onAdd()
this.resetTooltip()
},

View file

@ -38,6 +38,8 @@ L.U.Icon = L.DivIcon.extend({
formatUrl: function (url, feature) {
return L.Util.greedyTemplate(url || '', feature ? feature.extendedProperties() : {})
},
onAdd: function () {},
})
L.U.Icon.Default = L.U.Icon.extend({
@ -63,6 +65,19 @@ L.U.Icon.Default = L.U.Icon.extend({
this.elements.arrow.style.opacity = opacity
},
onAdd: function () {
const src = this._getIconUrl('icon')
// Decide whether to switch svg to white or not, but do it
// only for internal SVG, as invert could do weird things
if (src.startsWith('/') && src.endsWith('.svg')) {
const bgcolor = this._getColor()
// Must be called after icon container is added to the DOM
if (L.DomUtil.contrastedColor(this.elements.container, bgcolor)) {
this.elements.img.style.filter = 'invert(1)'
}
}
},
createIcon: function () {
this.elements = {}
this.elements.main = L.DomUtil.create('div')
@ -76,9 +91,9 @@ L.U.Icon.Default = L.U.Icon.extend({
if (src) {
// An url.
if (
src.indexOf('http') === 0 ||
src.indexOf('/') === 0 ||
src.indexOf('data:image') === 0
src.startsWith('http') ||
src.startsWith('/') ||
src.startsWith('data:image')
) {
this.elements.img = L.DomUtil.create('img', null, this.elements.container)
this.elements.img.src = src
@ -165,7 +180,6 @@ L.U.Icon.Ball = L.U.Icon.Default.extend({
},
})
const _CACHE_COLOR = {}
L.U.Icon.Cluster = L.DivIcon.extend({
options: {
iconSize: [40, 40],
@ -192,14 +206,6 @@ L.U.Icon.Cluster = L.DivIcon.extend({
if (this.datalayer.options.cluster && this.datalayer.options.cluster.textColor) {
color = this.datalayer.options.cluster.textColor
}
if (!color) {
if (typeof _CACHE_COLOR[backgroundColor] === 'undefined') {
color = L.DomUtil.TextColorFromBackgroundColor(el)
_CACHE_COLOR[backgroundColor] = color
} else {
color = _CACHE_COLOR[backgroundColor]
}
}
return color
return color || L.DomUtil.TextColorFromBackgroundColor(el, backgroundColor)
},
})