Skip to content

Commit

Permalink
Major and minor x-axis labels
Browse files Browse the repository at this point in the history
Adds options to
- specify major labels manually
- specify major labels automatically based on an interval
- specify major labels automatically based on a count
- suppress diplay of minor labels
- give major labels a different font size
The 'x_labels_num_limit' option has been removed. This functionality can also be achieved with the new options and now works for other graph types than Line.
  • Loading branch information
simplyarjen committed Mar 9, 2013
1 parent 1101bb8 commit 77a55bb
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 19 deletions.
21 changes: 17 additions & 4 deletions pygal/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,21 @@ class Config(object):
"Leave it to None to disable x labels display.",
str)

x_labels_num_limit = Key(None, int, "Label",
"Limits the number of X labels, defaults to None",
"If none, there will be as many x labels as provided in x_labels. When provided - limits the number of X labels"
)
x_labels_major = Key(
None, list, "Label",
"X labels that will be marked major.",
str)

x_labels_major_every = Key(
None, int, "Label",
"Mark every n-th x label as major.")

x_labels_major_count = Key(
None, int, "Label",
"Mark n evenly distributed labels as major.")

show_minor_x_labels = Key(
True, bool, "Label", "Set to false to hide x-labels not marked major")

y_labels = Key(
None, list, "Label",
Expand Down Expand Up @@ -198,6 +209,8 @@ class Config(object):
"No data", str, "Text", "Text to display when no data is given")

label_font_size = Key(10, int, "Text", "Label font size")

major_label_font_size = Key(10, int, "Text", "Major label font size")

value_font_size = Key(8, int, "Text", "Value font size")

Expand Down
5 changes: 5 additions & 0 deletions pygal/css/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
font-size: {{ font_sizes.label }};
}

.axis text.major {
font-family: monospace;
font-size: {{ font_sizes.major_label }};
}

.series text {
font-family: monospace;
font-size: {{ font_sizes.value }};
Expand Down
22 changes: 20 additions & 2 deletions pygal/graph/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,25 @@ def _x_axis(self, draw_axes=True):
d='M%f %f v%f' % (0, 0, self.view.height),
class_='line')
lastlabel = self._x_labels[-1][0]
if self.x_labels_major:
x_labels_major = self.x_labels_major
elif self.x_labels_major_every:
x_labels_major = [self._x_labels[i][0] for i in xrange(
0, len(self._x_labels), self.x_labels_major_every)]
elif self.x_labels_major_count:
label_count = len(self._x_labels)
major_count = self.x_labels_major_count
if (major_count >= label_count):
x_labels_major = [label[0] for label in self._x_labels]
else:
x_labels_major = [self._x_labels[
int(i * (label_count - 1) / (major_count - 1))][0]
for i in xrange(major_count)]
else:
x_labels_major = []
for label, position in self._x_labels:
major = is_major(position)
major = label in x_labels_major
if not (self.show_minor_x_labels or major): continue
guides = self.svg.node(axis, class_='guides')
x = self.view.x(position)
y = self.view.height + 5
Expand Down Expand Up @@ -162,7 +179,8 @@ def _x_axis(self, draw_axes=True):
secondary_ax = self.svg.node(
self.nodes['plot'], class_="axis x x2")
for label, position in self._x_2nd_labels:
major = is_major(position)
major = label in x_labels_major
if not (self.show_minor_x_labels or major): continue
# it is needed, to have the same structure as primary axis
guides = self.svg.node(secondary_ax, class_='guides')
x = self.view.x(position)
Expand Down
13 changes: 2 additions & 11 deletions pygal/graph/line.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,7 @@ def line(self, serie_node, serie, rescale=False):
self.svg.node(dots, 'circle', cx=x, cy=y, r=self.dots_size,
class_='dot reactive tooltip-trigger')
self._tooltip_data(
dots, "%s: %s" % (
self.x_labels[i], val)
if self.x_labels and self.x_labels_num_limit
else val, x, y)
dots, val, x, y)
self._static_value(
serie_node, val,
x + self.value_font_size,
Expand All @@ -114,13 +111,7 @@ def _compute(self):
self._points(x_pos)

if self.x_labels:
x_labels = zip(self.x_labels, x_pos)
if (self.x_labels_num_limit and
len(x_labels) > self.x_labels_num_limit):
step = (len(x_labels) - 1) / (self.x_labels_num_limit - 1)
x_labels = [x_labels[int(i * step)]
for i in range(self.x_labels_num_limit)]
self._x_labels = x_labels
self._x_labels = zip(self.x_labels, x_pos)
else:
self._x_labels = None

Expand Down
24 changes: 22 additions & 2 deletions pygal/graph/radar.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,39 @@ def _x_axis(self, draw_axes=True):
format_ = lambda x: '%f %f' % x
center = self.view((0, 0))
r = self._rmax
if self.x_labels_major:
x_labels_major = self.x_labels_major
elif self.x_labels_major_every:
x_labels_major = [self._x_labels[i][0] for i in xrange(
0, len(self._x_labels), self.x_labels_major_every)]
elif self.x_labels_major_count:
label_count = len(self._x_labels)
major_count = self.x_labels_major_count
if (major_count >= label_count):
x_labels_major = [label[0] for label in self._x_labels]
else:
x_labels_major = [self._x_labels[
int(i * label_count / major_count)][0]
for i in xrange(major_count)]
else:
x_labels_major = []

for label, theta in self._x_labels:
major = label in x_labels_major
if not (self.show_minor_x_labels or major): continue
guides = self.svg.node(axis, class_='guides')
end = self.view((r, theta))
self.svg.node(
guides, 'path',
d='M%s L%s' % (format_(center), format_(end)),
class_='line')
class_='%sline'%('major ' if major else ''))
r_txt = (1 - self._box.__class__.margin) * self._box.ymax
pos_text = self.view((r_txt, theta))
text = self.svg.node(
guides, 'text',
x=pos_text[0],
y=pos_text[1])
y=pos_text[1],
class_='major' if major else '')
text.text = label
angle = - theta + pi / 2
if cos(angle) < 0:
Expand Down

0 comments on commit 77a55bb

Please sign in to comment.