Browse Source

Work on worldmap, better svg + new data definition

pull/35/head
Florian Mounier 12 years ago
parent
commit
b9cc389c2d
  1. 12
      demo/moulinrouge/tests.py
  2. 27
      pygal/css/style.css
  3. 3
      pygal/graph/graph.py
  4. 48
      pygal/graph/worldmap.py
  5. 1
      pygal/graph/xy.py
  6. 1
      pygal/style.py
  7. 3
      pygal/util.py

12
demo/moulinrouge/tests.py

@ -167,7 +167,7 @@ def get_test_routes(app):
@app.route('/test/logarithmic/<chart>')
def test_logarithmic_for(chart):
graph = CHARTS_BY_NAME[chart](logarithmic=True)
if graph.__class__.__name__ == 'XY':
if isinstance(graph, CHARTS_BY_NAME['XY']):
graph.add('xy', [
(.1, .234), (10, 243), (.001, 2), (1000000, 1231)])
else:
@ -263,11 +263,11 @@ def get_test_routes(app):
@app.route('/test/worldmap')
def test_worldmap():
map = Worldmap()
map.add('fr', [13])
map.add('us', [10])
map.add('jp', [1])
map.add('ru', [7])
import random
map = Worldmap(style=random.choice(styles.values()))
map.add('1st', [('fr', 13), ('us', 10)])
map.add('2nd', [('jp', 1), ('ru', 7)])
return map.render_response()
return filter(lambda x: x.startswith('test'), locals())

27
pygal/css/style.css

@ -110,27 +110,20 @@ text.no_data {
}
.country {
fill: {{ style.primary }};
stroke: {{ style.primary }};
fill-opacity: .1;
opacity: {{ style.opacity }};
fill: {{ style.foreground }};
stroke: {{ style.plot_background }} !important;
opacity: .9;
stroke-width: 3;
-webkit-transition: 250ms;
-moz-transition: 250ms;
-o-transition: 250ms;
transition: 250ms;
}
.country:hover {
opacity: {{ style.opacity_hover }};
}
.lake {
fill: {{ style.foreground_dark }};
}
.borders {
fill: none;
stroke: {{ style.foreground_light }};
stroke-width: 0.3;
stroke-linecap: round;
stroke-linejoin: round;
opacity: 1;
}
{{ style.colors }}

3
pygal/graph/graph.py

@ -33,6 +33,7 @@ from itertools import repeat, izip, chain
class Graph(BaseGraph):
"""Graph super class containing generic common functions"""
_dual = False
def _decorate(self):
"""Draw all decorations"""
@ -50,7 +51,7 @@ class Graph(BaseGraph):
def _set_view(self):
"""Assign a view to current graph"""
if self.logarithmic:
if self.__class__.__name__ == 'XY':
if self._dual:
view_class = XYLogView
else:
view_class = LogView

48
pygal/graph/worldmap.py

@ -22,7 +22,7 @@ Worldmap chart
"""
from __future__ import division
from pygal.util import cut
from pygal.util import cut, cached_property
from pygal.graph.graph import Graph
from pygal.adapters import positive, none_to_zero
from lxml import etree
@ -36,25 +36,45 @@ with open(os.path.join(
class Worldmap(Graph):
"""Worldmap graph"""
_adapters = [positive, none_to_zero]
_dual = True
@cached_property
def countries(self):
return [val[0]
for serie in self.all_series
for val in serie.values
if val[0] is not None]
@cached_property
def _values(self):
"""Getter for series values (flattened)"""
return [val[1]
for serie in self.series
for val in serie.values
if val[1] is not None]
def _plot(self):
map = etree.fromstring(MAP)
map.set('width', str(self.view.width))
map.set('height', str(self.view.height))
sum_ = sum(cut(cut(self.series, 'values')))
for i, serie in enumerate(self.series):
ratio = serie.values[0] / self._max
perc = serie.values[0] / sum_ if sum_ != 0 else 0
country = map.find('.//*[@id="%s"]' % serie.title)
if country is None:
continue
country.set(
'style', 'fill-opacity: %f' % (
ratio))
title = country[0]
title.text = (title.text or '?') + ': %d (%s)' % (
serie.values[0], '{0:.2%}'.format(perc))
min_ = min(cut(serie.values, 1))
max_ = max(cut(serie.values, 1))
for country, value in serie.values:
if value is None:
continue
ratio = value / (max_ - min_)
country = map.find('.//*[@id="%s"]' % country)
if country is None:
continue
cls = country.get('class', '').split(' ')
cls.append('color-%d' % i)
country.set('class', ' '.join(cls))
country.set(
'style', 'fill-opacity: %f' % (
ratio))
title = country[0]
title.text = (title.text or '?') + ': %d' % value
self.nodes['plot'].append(map)

1
pygal/graph/xy.py

@ -28,6 +28,7 @@ from pygal.graph.line import Line
class XY(Line):
"""XY Line graph"""
_dual = True
@cached_property
def xvals(self):

1
pygal/style.py

@ -48,7 +48,6 @@ class Style(object):
self.opacity_hover = opacity_hover
self.transition = transition
self._colors = colors
self.primary = colors[0]
@property
def colors(self):

3
pygal/util.py

@ -297,7 +297,6 @@ from pygal.serie import Serie
def prepare_values(raw, config, cls):
"""Prepare the values to start with sane values"""
from pygal.graph.xy import XY
from pygal.graph.datey import DateY
if not raw:
@ -336,7 +335,7 @@ def prepare_values(raw, config, cls):
else:
value = raw_value
if issubclass(cls, XY):
if cls._dual:
if value is None:
value = (None, None)
elif not hasattr(value, '__iter__'):

Loading…
Cancel
Save