使用背景填充向散景图添加文本
Adding text to a bokeh plot with a background fill
我目前有一个 bokeh.models.glyphs.Text
可以向绘图中添加一些文本。现在我想填充文本标签的背景,但是 bokeh.models.glyphs.Text
没有 background_fill
参数。
是否有其他方法可以将带有背景填充的文本添加到散景图?
您无法使用 Text
字形本身来完成此操作。但还有其他选择:
- 在文本正下方绘制一个所需颜色的矩形。非常容易实现但很难测量文本,以便所有矩形始终具有所需的宽度
- 创建一个自定义
Text
模型来为您绘制矩形。实施起来有点困难,因为它需要一些 JavaScript/TypeScript,但它将能够自动测量文本
这是一个简单的示例,它不完全是一个文本框,而是一个使用 LabelSet()
对象的行列表。 LabelSet()
是一种在图形 window 中的多个位置放置标签的方法。它有更好的支持,通常包括:
- 背景颜色
source=
字段 ColumnDataSource
data
或 screen
个单位
如果您将 LabelSet
个位置放置得足够近,字体大小合适,它看起来就像一个文本框。
这是一个示例,其中包含一个按钮,每次按下该按钮时都会使用当前日期更新文本:
import numpy as np
from datetime import datetime
from bokeh.layouts import layout
from bokeh.io import curdoc
from bokeh.models import ColumnDataSource, Button, LabelSet
from bokeh.plotting import figure
nLines=4 # max number of lines
text_str = ['{0}'.format(line) for line in range(nLines)] # init with empty strings
# create some other data coordinates for a figure
xData=np.arange(-3,+12,0.5)
yData=xData
plot = figure(title="Text placement example, in screen units",
height=300, sizing_mode='scale_width',
x_range=(min(xData), max(xData)), y_range=(min(yData), max(yData)),
x_axis_label="my X-axis", y_axis_label="my Y-axis")
# ------------ text box with a LabelSet() object ----------------
x_scr_lo=20; x_scr_hi=67
label_data = ColumnDataSource(data=dict(
x=[x_scr_lo]*nLines,
y=np.linspace(x_scr_lo,x_scr_hi,nLines),
text=text_str))
plot_label = LabelSet(x='x', y='y', text='text',
text_font_size='11pt',
background_fill_color='lightskyblue',
x_units='screen', y_units='screen',
background_fill_alpha=0.2,
text_color='blue', source=label_data)
plot.add_layout(plot_label)
def bt_add_lines_callback():
new_text=label_data.data['text'] # grab current string list
new_text.pop() # drop the oldest (last)
new_text.insert(0, 'update {0}'.format( datetime.now().strftime('%c') ) )
label_data.data=dict(x=[20]*nLines,
y=np.linspace(x_scr_lo,x_scr_hi,nLines), text=new_text)
bt_add_lines = Button(label="Update next line" ,
button_type="success", width=200)
bt_add_lines.on_click(bt_add_lines_callback)
## arrange all map views in a grid layout then add to the document
layout = layout([
[bt_add_lines],
[plot] ], sizing_mode='stretch_width')
doc = curdoc()
doc.add_root(layout)
我目前有一个 bokeh.models.glyphs.Text
可以向绘图中添加一些文本。现在我想填充文本标签的背景,但是 bokeh.models.glyphs.Text
没有 background_fill
参数。
是否有其他方法可以将带有背景填充的文本添加到散景图?
您无法使用 Text
字形本身来完成此操作。但还有其他选择:
- 在文本正下方绘制一个所需颜色的矩形。非常容易实现但很难测量文本,以便所有矩形始终具有所需的宽度
- 创建一个自定义
Text
模型来为您绘制矩形。实施起来有点困难,因为它需要一些 JavaScript/TypeScript,但它将能够自动测量文本
这是一个简单的示例,它不完全是一个文本框,而是一个使用 LabelSet()
对象的行列表。 LabelSet()
是一种在图形 window 中的多个位置放置标签的方法。它有更好的支持,通常包括:
- 背景颜色
source=
字段ColumnDataSource
data
或screen
个单位
如果您将 LabelSet
个位置放置得足够近,字体大小合适,它看起来就像一个文本框。
这是一个示例,其中包含一个按钮,每次按下该按钮时都会使用当前日期更新文本:
import numpy as np
from datetime import datetime
from bokeh.layouts import layout
from bokeh.io import curdoc
from bokeh.models import ColumnDataSource, Button, LabelSet
from bokeh.plotting import figure
nLines=4 # max number of lines
text_str = ['{0}'.format(line) for line in range(nLines)] # init with empty strings
# create some other data coordinates for a figure
xData=np.arange(-3,+12,0.5)
yData=xData
plot = figure(title="Text placement example, in screen units",
height=300, sizing_mode='scale_width',
x_range=(min(xData), max(xData)), y_range=(min(yData), max(yData)),
x_axis_label="my X-axis", y_axis_label="my Y-axis")
# ------------ text box with a LabelSet() object ----------------
x_scr_lo=20; x_scr_hi=67
label_data = ColumnDataSource(data=dict(
x=[x_scr_lo]*nLines,
y=np.linspace(x_scr_lo,x_scr_hi,nLines),
text=text_str))
plot_label = LabelSet(x='x', y='y', text='text',
text_font_size='11pt',
background_fill_color='lightskyblue',
x_units='screen', y_units='screen',
background_fill_alpha=0.2,
text_color='blue', source=label_data)
plot.add_layout(plot_label)
def bt_add_lines_callback():
new_text=label_data.data['text'] # grab current string list
new_text.pop() # drop the oldest (last)
new_text.insert(0, 'update {0}'.format( datetime.now().strftime('%c') ) )
label_data.data=dict(x=[20]*nLines,
y=np.linspace(x_scr_lo,x_scr_hi,nLines), text=new_text)
bt_add_lines = Button(label="Update next line" ,
button_type="success", width=200)
bt_add_lines.on_click(bt_add_lines_callback)
## arrange all map views in a grid layout then add to the document
layout = layout([
[bt_add_lines],
[plot] ], sizing_mode='stretch_width')
doc = curdoc()
doc.add_root(layout)