Plotly 图形组件无法接受视口单位来设置文本注释字体大小
Plotly graph component cannot accept viewport units to set text annotation font size
我正在使用 Plotly-Dash 并且需要我的文本注释的字体大小随视口宽度缩放,就像我的图表一样。对于我布局中的各种 headers,我可以直接设置 font-size: '1vw'
,但是 vw
不是为 style
属性设置 font-size
的可接受单位dcc.Graph
个组件。这是相关的回溯:
ValueError:
Invalid element(s) received for the 'size' property of scatter.textfont
Invalid elements include: ['1vw', '1vw', '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
我认为如果 dcc.Graph
组件可以接受视口单位(例如 style = {height: 30vw, width: 30vw}
)并简单地将它们转换为像素 browser-side,那么我应该能够执行类似的转换与 font-size
.
Python 端是否有方法以像素为单位检索视口宽度,以便我可以对字体大小执行自己的缩放逻辑?
这是一个演示此行为的示例 Dash 应用程序:
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 __name__ == '__main__':
app.run_server()
根据我环顾四周的了解,没有办法只使用 plotly-dash
来做到这一点。
您需要实现的基本上是 "responsive" 排版,这个主题有一些非常有趣的文章:
- https://css-tricks.com/books/volume-i/scale-typography-screen-size/
- https://css-tricks.com/snippets/css/fluid-typography/
- 字体大小使用
em
单位:https://developer.mozilla.org/en-US/docs/Web/CSS/font-size#Ems
Dash 提供 option to override the default CSS and JS of an app and you can see from the layout documentation,如何使用外部 CSS 文件。
我的建议:研究生成的页面以了解文本注释是如何被标记的 (id
and/or class
) 并使用上面文章中提供的方法来创建一个令人满意的结果。 (很抱歉,除了建议,我真的不能做更多,但我还没有看到你的代码示例:/)
编辑(评论和问题编辑后):
因此,由于文本注释具有 class textpoint
,我们将 override the default CSS:
创建建议的文件夹结构:
- app.py
- assets/
|--- typography.css
在 typography.css
上应用上述方法之一(我将按照第二个带项目符号的示例进行):
.textpoint{
font-size: calc(14px + (26 - 14) * ((100vw - 300px) / (1600 - 300)));
}
编辑#2:
我发现了问题和解决方法:
- 在 Dash 版本 >= 0.22 上添加自定义 CSS 的方法确实是上面的并且有效。
- 为了将自定义规则应用于注释,我们需要定位的元素是
.textpoint
class 中的 text
标记(CSS 语法: .textpoint text
)
- 出于某种原因,自定义 CSS 规则被覆盖(可能出于类似的原因,在此 SO post 的最佳答案中进行了解释:custom css being overridden by bootstrap css)。所以我们需要
!important
的"nuclear"选项。
利用以上内容,typography.css
应该如下所示:
.textpoint text{
font-size: calc(14px + (26 - 14) * ((100vw - 300px) / (1600 - 300))) !important;
}
错误消息说您应该将大小作为 int
对象提及。
如果你不能在代码中直接使用vw,尝试使用PySide/PyQt获取它,然后将其转换为int
并保存在不同的变量width
& height
下你可以插入而不是 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())
我不知道你用的是什么代码,所以我没有试过。让我知道它是否适合你。
我正在使用 Plotly-Dash 并且需要我的文本注释的字体大小随视口宽度缩放,就像我的图表一样。对于我布局中的各种 headers,我可以直接设置 font-size: '1vw'
,但是 vw
不是为 style
属性设置 font-size
的可接受单位dcc.Graph
个组件。这是相关的回溯:
ValueError: Invalid element(s) received for the 'size' property of scatter.textfont Invalid elements include: ['1vw', '1vw', '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
我认为如果 dcc.Graph
组件可以接受视口单位(例如 style = {height: 30vw, width: 30vw}
)并简单地将它们转换为像素 browser-side,那么我应该能够执行类似的转换与 font-size
.
Python 端是否有方法以像素为单位检索视口宽度,以便我可以对字体大小执行自己的缩放逻辑?
这是一个演示此行为的示例 Dash 应用程序:
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 __name__ == '__main__':
app.run_server()
根据我环顾四周的了解,没有办法只使用 plotly-dash
来做到这一点。
您需要实现的基本上是 "responsive" 排版,这个主题有一些非常有趣的文章:
- https://css-tricks.com/books/volume-i/scale-typography-screen-size/
- https://css-tricks.com/snippets/css/fluid-typography/
- 字体大小使用
em
单位:https://developer.mozilla.org/en-US/docs/Web/CSS/font-size#Ems
Dash 提供 option to override the default CSS and JS of an app and you can see from the layout documentation,如何使用外部 CSS 文件。
我的建议:研究生成的页面以了解文本注释是如何被标记的 (id
and/or class
) 并使用上面文章中提供的方法来创建一个令人满意的结果。 (很抱歉,除了建议,我真的不能做更多,但我还没有看到你的代码示例:/)
编辑(评论和问题编辑后):
因此,由于文本注释具有 class textpoint
,我们将 override the default CSS:
创建建议的文件夹结构:
- app.py - assets/ |--- typography.css
在
typography.css
上应用上述方法之一(我将按照第二个带项目符号的示例进行):.textpoint{ font-size: calc(14px + (26 - 14) * ((100vw - 300px) / (1600 - 300))); }
编辑#2:
我发现了问题和解决方法:
- 在 Dash 版本 >= 0.22 上添加自定义 CSS 的方法确实是上面的并且有效。
- 为了将自定义规则应用于注释,我们需要定位的元素是
.textpoint
class 中的text
标记(CSS 语法:.textpoint text
) - 出于某种原因,自定义 CSS 规则被覆盖(可能出于类似的原因,在此 SO post 的最佳答案中进行了解释:custom css being overridden by bootstrap css)。所以我们需要
!important
的"nuclear"选项。
利用以上内容,typography.css
应该如下所示:
.textpoint text{
font-size: calc(14px + (26 - 14) * ((100vw - 300px) / (1600 - 300))) !important;
}
错误消息说您应该将大小作为 int
对象提及。
如果你不能在代码中直接使用vw,尝试使用PySide/PyQt获取它,然后将其转换为int
并保存在不同的变量width
& height
下你可以插入而不是 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())
我不知道你用的是什么代码,所以我没有试过。让我知道它是否适合你。