mirror of https://github.com/Kozea/pygal.git
Florian Mounier
13 years ago
8 changed files with 124 additions and 0 deletions
@ -0,0 +1,3 @@
|
||||
from collections import namedtuple |
||||
|
||||
Serie = namedtuple('Serie', ('title', 'values')) |
@ -0,0 +1,13 @@
|
||||
|
||||
|
||||
class BaseGraph(object): |
||||
"""Graphs commons""" |
||||
|
||||
def render(self): |
||||
self.draw() |
||||
return self.svg.render() |
||||
|
||||
def _in_browser(self): |
||||
from lxml.html import open_in_browser |
||||
self.draw() |
||||
open_in_browser(self.svg.root, encoding='utf-8') |
@ -0,0 +1,26 @@
|
||||
from pygal import Serie |
||||
from pygal.svg import Svg |
||||
from pygal.base import BaseGraph |
||||
|
||||
|
||||
class Line(BaseGraph): |
||||
"""Line graph""" |
||||
|
||||
def __init__(self, width, height): |
||||
self.width = width |
||||
self.height = height |
||||
self.svg = Svg(width, height) |
||||
self.series = [] |
||||
|
||||
def add(self, title, values): |
||||
self.series.append( |
||||
Serie(title, values)) |
||||
|
||||
def draw(self): |
||||
self.svg.graph() |
||||
for serie in self.series: |
||||
n_values = len(serie.values) |
||||
x_spacing = self.width / n_values |
||||
self.svg.line([ |
||||
(i * x_spacing, v) |
||||
for i, v in enumerate(serie.values)]) |
@ -0,0 +1,52 @@
|
||||
from lxml import etree |
||||
|
||||
|
||||
class Svg(object): |
||||
"""Svg object""" |
||||
ns = 'http://www.w3.org/2000/svg' |
||||
|
||||
def __init__(self, width, height): |
||||
self.width = width |
||||
self.height = height |
||||
self.root = etree.Element( |
||||
"{%s}svg" % self.ns, |
||||
attrib={ |
||||
'viewBox': '0 0 %d %d' % (width, height) |
||||
}, |
||||
nsmap={ |
||||
None: self.ns, |
||||
'xlink': 'http://www.w3.org/1999/xlink', |
||||
}) |
||||
|
||||
def node(self, parent=None, tag='g', attrib=None, **extras): |
||||
if parent is None: |
||||
parent = self.root |
||||
attrib = attrib or {} |
||||
attrib.update(extras) |
||||
for key, value in attrib.items(): |
||||
if not isinstance(value, basestring): |
||||
attrib[key] = str(value) |
||||
if key == 'class_': |
||||
attrib['class'] = attrib['class_'] |
||||
del attrib['class_'] |
||||
|
||||
return etree.SubElement(parent, tag, attrib) |
||||
|
||||
def format_coords(self, xy): |
||||
return '%f %f' % xy |
||||
|
||||
def graph(self): |
||||
self.graph = self.node(id='graph') |
||||
self.node(self.graph, 'rect', id='graph_background', |
||||
x=0, y=0, width=self.width, height=self.height) |
||||
|
||||
def line(self, values, origin=None): |
||||
origin = self.format_coords(origin or values[0]) |
||||
values = ' '.join(map(self.format_coords, values)) |
||||
self.node(self.graph, 'path', |
||||
d='M%s L%s' % (origin, values)) |
||||
|
||||
def render(self): |
||||
return etree.tostring( |
||||
self.root, pretty_print=True, |
||||
xml_declaration=True, encoding='utf-8') |
@ -0,0 +1,7 @@
|
||||
from pygal.line import Line |
||||
|
||||
|
||||
def test_simple_line(): |
||||
line = Line(800, 600) |
||||
line.add('test', [10, 20, 5, 17]) |
||||
line._in_browser() |
@ -0,0 +1,11 @@
|
||||
from pygal.svg import Svg |
||||
|
||||
|
||||
def test_root(): |
||||
svg = Svg(800, 600) |
||||
assert svg.render() == ('\n'.join(( |
||||
'<?xml version=\'1.0\' encoding=\'utf-8\'?>', |
||||
'<svg xmlns:xlink="http://www.w3.org/1999/xlink" ' |
||||
'xmlns="http://www.w3.org/2000/svg" ' |
||||
'viewBox="0 0 800 600"/>', |
||||
''))) |
Loading…
Reference in new issue