web-dev-qa-db-fra.com

Le composant graphique de tracé ne peut pas accepter les unités de la fenêtre d'affichage pour définir la taille de police de l'annotation textuelle

J'utilise Plotly-Dash et j'ai besoin de la taille de la police de mes annotations textuelles pour s'adapter à la largeur de la fenêtre d'affichage, comme le font mes graphiques. Pour différents en-têtes de ma mise en page, je peux définir directement font-size: '1vw'; cependant, vw n'est pas une unité acceptée pour définir le font-size pour l'attribut style d'un composant dcc.Graph. Voici le traceback associé:

ValueError: Elément (s) non valide (s) reçu (s) pour la propriété 'size' de scatter.textfont Les éléments invalides incluent: ['1vw', '1vw', '1vw', '1vw', '1vw', '1vw', '1vw', '1vw']

The 'size' property is a number and may be specified as:
  - An int or float in the interval [1, inf]
  - A Tuple, list, or one-dimensional numpy array of the above

Je suppose que si le composant dcc.Graph peut accepter les unités de la fenêtre de visualisation (par exemple, style = {height: 30vw, width: 30vw}) et les convertir simplement en pixels côté navigateur, je devrais pouvoir effectuer une conversion similaire avec le font-size.

Y a-t-il un moyen du côté Python de récupérer la largeur de la fenêtre d'affichage en pixels, afin que je puisse effectuer ma propre logique de mise à l'échelle pour la taille de la police?

Voici un exemple d'application Dash qui illustre ce problème:

import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go

labels = {'Point 1': (3.5,5), 'Point 2': (1.5,2), 'Point 3': (3.5,8)}

app = dash.Dash(__name__)

app.layout = html.Div([

    html.H1('Test', id='test', style={'margin': 50}),

    dcc.Graph(id='my-plot', style={'margin': 10}),

])

@app.callback(
    Output('my-plot', 'figure'),
    [Input('test', 'children')])
def update_graph(val):

    return {

        'data': [go.Scatter(
            x=[v[0]],
            y=[v[1]],
            text=k,
            mode='text'
        ) for k, v in labels.items()],

        'layout': go.Layout(
            margin={'l': 40, 'b': 40, 't': 40, 'r': 40},
            shapes=[
                {
                    'type': 'path',
                    'path': ' M 1 1 L 1 3 L 4 1 Z',
                    'fillcolor': 'rgba(44, 160, 101, 0.5)',
                    'line': {
                        'color': 'rgb(44, 160, 101)',
                    }
                },
                {
                    'type': 'path',
                    'path': ' M 3,7 L2,8 L2,9 L3,10, L4,10 L5,9 L5,8 L4,7 Z',
                    'fillcolor': 'rgba(255, 140, 184, 0.5)',
                    'line': {
                        'color': 'rgb(255, 140, 184)',
                    }
                },
            ]
        )
    }

if __== '__main__':
    app.run_server()
8
rahlf23

D'après ce que j'ai compris en regardant autour de moi, il n'y a pas de moyen de faire cela en utilisant uniquement le plotly-dash. Ce que vous devez réaliser est essentiellement une typographie "réactive", un sujet dans lequel sont écrits des articles très intéressants:

Dash offre l'option pour remplacer les CSS et JS par défaut d'une application et vous pouvez voir à partir de la documentation layout , comment utiliser même des fichiers CSS externes.

Ma suggestion: Recherchez dans la page résultante comment les annotations textuelles sont marquées (id et/ou class) et utilisez les méthodes fournies dans les articles ci-dessus pour créer un résultat satisfaisant. (Je suis désolé de ne pouvoir faire que suggérer, mais je n'ai pas vu d'exemple de votre code: /)


EDIT (après la modification des commentaires et des questions):

Donc, puisque les annotations textuelles ont la classe textpoint, nous allons remplacer le CSS par défaut :

  1. Créez la structure de dossiers suggérée:

    - app.py
    - assets/
    |--- typography.css
    
  2. Sur le typography.css, appliquez l’une des méthodes mentionnées ci-dessus (je vais au deuxième exemple à puces):

    .textpoint{
        font-size: calc(14px + (26 - 14) * ((100vw - 300px) / (1600 - 300)));
    }
    

EDIT # 2:

J'ai trouvé le problème et une solution de contournement:

  • La méthode pour ajouter des CSS personnalisés sur la version Dash> = 0.22 est bien la précédente et cela fonctionne.
  • L'élément que nous devons cibler pour appliquer notre règle personnalisée aux annotations est une balise text à l'intérieur de la classe .textpoint (syntaxe CSS: .textpoint text).
  • Pour une raison quelconque, la règle CSS personnalisée est remplacée (probablement pour une raison similaire, expliquée dans la première réponse de cet article SO: les flux de données personnalisés sont remplacés par bootstrap css ). Nous avons donc besoin de l'option "nucléaire" de !important.

En utilisant ce qui précède, le typography.css devrait ressembler à ceci:

.textpoint text{
  font-size: calc(14px + (26 - 14) * ((100vw - 300px) / (1600 - 300))) !important;
}
2
John Moutafis

Le message d'erreur indique que vous devez indiquer la taille sous la forme d'un objet int . Si vous ne pouvez pas utiliser directement vw dans votre code, essayez de l'obtenir avec PySide/PyQt, puis convertissez-le en int et enregistrez-le sous un variable width & height que vous pouvez insérer au lieu de vw.

from PySide import QtGui
#replace that with "from PyQt4 import QtGui" if you're using PyQt4

app = QtGui.QApplication([])
screen_resolution = app.desktop().screenGeometry()
width = int(screen_resolution.width())
height = int(screen_resolution.height())

Je ne sais pas avec quel code vous travaillez, donc je ne l'ai pas essayé. Faites-moi savoir si cela fonctionne pour vous.

0
bkirthi