我想将pygal图表中的点从默认的圆更改为矩形(听起来很奇怪,但就我而言是有意义的),并能够定义矩形的大小。我在文档中找不到解决方案。使用配置模块,我可以显示/隐藏点并更改点的大小,但据我所知我无法更改点图标。我也无法在样式模块中找到解决方案。
有简单的方法吗?
非常感谢
答案 0 :(得分:0)
无法使用样式或配置来实现此目的:圆点被硬编码到呈现折线图的函数中。但是,您可以轻松地扩展折线图类并覆盖此功能以创建具有任何点形的图表。
如果您查看source code of the Line
class,则会在line
函数中看到以下代码:
alter(
self.svg.transposable_node(
dots,
'circle',
cx=x,
cy=y,
r=serie.dots_size,
class_='dot reactive tooltip-trigger'
), metadata
)
这将为每个点创建一个圆并将其添加到将用于生成图表的SVG数据中。
将整个函数复制到新类中,并用以下代码替换这些行。使用dots_size
配置来确定宽度和高度,这将添加正方形而不是圆形:
alter(
self.svg.transposable_node(
dots,
'rect',
x=x - serie.dots_size / 2,
y=y - serie.dots_size / 2,
width=serie.dots_size,
height=serie.dots_size,
class_='dot reactive tooltip-trigger'
), metadata
)
完整的类看起来像这样(看起来像很多代码,但大多数都是复制粘贴的):
from pygal.util import alter, decorate
class SquareDots(pygal.Line):
def __init__(self, *args, **kwargs):
super(SquareDots, self).__init__(*args, **kwargs)
def line(self, serie, rescale=False):
serie_node = self.svg.serie(serie)
if rescale and self.secondary_series:
points = self._rescale(serie.points)
else:
points = serie.points
view_values = list(map(self.view, points))
if serie.show_dots:
for i, (x, y) in enumerate(view_values):
if None in (x, y):
continue
if self.logarithmic:
if points[i][1] is None or points[i][1] <= 0:
continue
if (serie.show_only_major_dots and self.x_labels
and i < len(self.x_labels)
and self.x_labels[i] not in self._x_labels_major):
continue
metadata = serie.metadata.get(i)
classes = []
if x > self.view.width / 2:
classes.append('left')
if y > self.view.height / 2:
classes.append('top')
classes = ' '.join(classes)
self._confidence_interval(
serie_node['overlay'], x, y, serie.values[i], metadata
)
dots = decorate(
self.svg,
self.svg.node(serie_node['overlay'], class_="dots"),
metadata
)
val = self._format(serie, i)
# This is the part that needs to be changed.
alter(self.svg.transposable_node(
dots,
'rect',
x=x - serie.dots_size / 2,
y=y - serie.dots_size / 2,
width=serie.dots_size,
height=serie.dots_size,
class_='dot reactive tooltip-trigger'
), metadata
)
self._tooltip_data(
dots, val, x, y, xlabel=self._get_x_label(i)
)
self._static_value(
serie_node, val, x + self.style.value_font_size,
y + self.style.value_font_size, metadata
)
if serie.stroke:
if self.interpolate:
points = serie.interpolated
if rescale and self.secondary_series:
points = self._rescale(points)
view_values = list(map(self.view, points))
if serie.fill:
view_values = self._fill(view_values)
if serie.allow_interruptions:
sequences = []
cur_sequence = []
for x, y in view_values:
if y is None and len(cur_sequence) > 0:
sequences.append(cur_sequence)
cur_sequence = []
elif y is None:
continue
else:
cur_sequence.append((x, y))
if len(cur_sequence) > 0:
sequences.append(cur_sequence)
else:
sequences = [view_values]
if self.logarithmic:
for seq in sequences:
for ele in seq[::-1]:
y = points[seq.index(ele)][1]
if y is None or y <= 0:
del seq[seq.index(ele)]
for seq in sequences:
self.svg.line(
serie_node['plot'],
seq,
close=self._self_close,
class_='line reactive' +
(' nofill' if not serie.fill else '')
)
然后您的新类就可以像其他任何pygal图表一样使用。
chart = SquareDots(dots_size=50)
chart.add("line", [1, 2, 3, 4, 3, 2])
chart.render_to_png("chart.png")