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()
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:
em
unités: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size#EmsDash 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 :
Créez la structure de dossiers suggérée:
- app.py
- assets/
|--- typography.css
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:
text
à l'intérieur de la classe .textpoint
(syntaxe CSS: .textpoint text
).!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;
}
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.