plotly / plotly/plotly.js

[BUG]: marker.colorbar.tickfont.textcase='normal' blanks scattermap on initial render, but Plotly.restyle renders correctly

Abierto
#7,869 4 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

bug good first issue good for agent P3 size: 3
Lenguaje dominante
JavaScript
Estrellas
18.3k
Forks
2k
Merge medio
2 d 12 h
PR fusionados (30 d)
28

Descripción

Description

When initializing a Plotly Scattermap figure with
marker.colorbar.tickfont.textcase='normal', the initial render can fail to draw the
OpenStreetMap tiles and map-layer geometry. The figure area is mostly blank, with only
right-side numeric tick labels and the OpenStreetMap attribution visible.

However, if the same base figure is rendered first and the same property value is
then applied dynamically through Plotly.restyle, the map renders correctly: the OSM
tiles appear, the blue filled map layer is visible, and the cyan marker is drawn.

The setting is accepted by plotly.py and emitted as a valid trace property, so this
appears to be an initial-render/update-time rendering discrepancy involving
Scattermap marker colorbar tick font defaults rather than an invalid Python-side
property assignment.

Screenshots/Video
Image Image
Steps to reproduce
import io
import time

import plotly
import plotly.graph_objects as go
import plotly.io as pio
from PIL import Image, ImageChops
from playwright.sync_api import sync_playwright

print(f"Plotly version: {plotly.__version__}")


def make_fig():
    fig = go.Figure(
        go.Scattermap(
            mode="markers",
            lon=[-73.605],
            lat=[45.51],
            marker={"size": 20, "color": ["cyan"]},
        )
    )

    polygon = [
        [
            [
                [-73.62, 45.50],
                [-73.59, 45.50],
                [-73.59, 45.53],
                [-73.62, 45.53],
                [-73.62, 45.50],
            ]
        ]
    ]

    fig.update_layout(
        map={
            "style": "open-street-map",
            "center": {"lon": -73.6, "lat": 45.5},
            "zoom": 12,
            "layers": [
                {
                    "source": {
                        "type": "FeatureCollection",
                        "features": [
                            {
                                "type": "Feature",
                                "geometry": {
                                    "type": "MultiPolygon",
                                  "coordinates": polygon,
                                },
                            }
                        ],
                    },
                    "type": "fill",
                    "below": "traces",
                    "color": "royalblue",
                }
            ],
        },
        margin={"l": 0, "r": 0, "b": 0, "t": 0},
    )
    return fig


fig = make_fig()

# Screenshot 1 / plot1.png: set the value in Python before the first render.
fig.data[0].marker.colorbar.tickfont.textcase = "normal"
assert fig.data[0].marker.colorbar.tickfont.textcase == "normal"
print("Python-side tickfont JSON:", fig.data[0].marker.colorbar.tickfont.to_plotly_json())
html1 = pio.to_html(fig, full_html=True, include_plotlyjs="cdn")


# Screenshot 2 / plot2.png: render first, then apply the same value with JS.
fig.data[0].marker.colorbar.tickfont.textcase = None
html2 = pio.to_html(fig, full_html=True, include_plotlyjs="cdn")
restyle_script = """
<script>
window.addEventListener("DOMContentLoaded", () => {
    const plotEl = document.getElementsByClassName("plotly-graph-div")[0];
    setTimeout(() => {
        Plotly.restyle(plotEl, {"marker.colorbar.tickfont.textcase": "normal"}, [0]);
    }, 1000);
});
</script>
"""
html2 = html2.replace("</body>", restyle_script + "\n</body>")


with sync_playwright() as p:
    browser = p.chromium.launch(
        headless=True,
        args=["--no-sandbox", "--disable-dev-shm-usage", "--disable-gpu"],
    )
    page = browser.new_page(viewport={"width": 1200, "height": 800})

    page.set_content(html1)
    time.sleep(1.5)
    img1 = page.screenshot(path="plot1.png")

    page.set_content(html2)
    time.sleep(2.0)
    img2 = page.screenshot(path="plot2.png")

    browser.close()

diff = ImageChops.difference(
    Image.open(io.BytesIO(img1)).convert("RGB"),
    Image.open(io.BytesIO(img2)).convert("RGB"),
)

print("Saved plot1.png and plot2.png")
assert diff.getbbox() is not None, "Reproducer did not reproduce: images are identical."
Notes

Add info here that doesn't fit in the other sections.

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Comienza con el reproductor de Python/Playwright proporcionado y compara el renderizado inicial de Scattermap con la llamada posterior a Plotly.restyle. Sigue el procesamiento de marker colorbar tickfont.textcase durante la inicialización y considera terminado el issue cuando ambas rutas rendericen correctamente los mosaicos de OpenStreetMap, la geometría de la capa del mapa y el marcador cian.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
javascript, playwright, python
Área
data-visualization
Tipo de issue
Error
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Tranquilo
Claridad
Bastante claro
Aptitud para principiantes
50/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.