From 96c4148232bf80b7d7e6a21ed5ad4165c5bac929 Mon Sep 17 00:00:00 2001 From: Maarten Breddels Date: Tue, 11 Jul 2023 15:13:53 +0200 Subject: [PATCH] fix: background color of figure was not computed properly (#1603) On the screen, it is not the computed background color that is seen by a user. Since DOM elements can be transparent, the background color might be one of the parent elements. This is why we need to traverse the DOM tree to find the background color of the first non-transparent parent element. A more sophisticated solution would be to also use blending when there is a non-fully transparent background color. I think that might be a bit overkill for now. See also https://github.com/spacetelescope/jdaviz/pull/2264#issuecomment-1612052525 --- js/src/Figure.ts | 4 ++-- js/src/utils.ts | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/js/src/Figure.ts b/js/src/Figure.ts index 8e6c8db85..3ba965aa5 100644 --- a/js/src/Figure.ts +++ b/js/src/Figure.ts @@ -28,7 +28,7 @@ import { Scale, ScaleModel } from 'bqscales'; import * as popperreference from './PopperReference'; import popper from 'popper.js'; -import { applyAttrs, applyStyles } from './utils'; +import { applyAttrs, applyStyles, getEffectiveBackgroundColor } from './utils'; import { AxisModel } from './AxisModel'; import { Mark } from './Mark'; import { MarkModel } from './MarkModel'; @@ -1105,7 +1105,7 @@ export class Figure extends DOMWidgetView { svg.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); svg.setAttribute('width', this.width); svg.setAttribute('height', this.height); - svg.style.background = window.getComputedStyle(document.body).background; + svg.style.background = getEffectiveBackgroundColor(this.el); const computedStyle = window.getComputedStyle(this.el); const cssCode = diff --git a/js/src/utils.ts b/js/src/utils.ts index b8742546f..8dc7b328f 100644 --- a/js/src/utils.ts +++ b/js/src/utils.ts @@ -124,3 +124,23 @@ export function d3GetEvent() { export function getLuminoWidget(ipywidget: DOMWidgetView) { return ipywidget.pWidget ? ipywidget.pWidget : ipywidget.luminoWidget; } + +export function getEffectiveBackgroundColor(element) { + if (!element) { + // If no element provided or we have traversed beyond the body or html, + // we default to white as the background color. + return 'rgb(255, 255, 255)'; + } + + const style = window.getComputedStyle(element); + const bgColor = style.backgroundColor; + const hasBackgroundImage = style.backgroundImage !== 'none'; + const isTransparent = + bgColor === 'transparent' || bgColor === 'rgba(0, 0, 0, 0)'; + + if (!isTransparent || hasBackgroundImage) { + return bgColor; + } + + return getEffectiveBackgroundColor(element.parentElement); +}