From b9cc389c2dd6525b361f0d9a83aa09f7122e0566 Mon Sep 17 00:00:00 2001 From: Florian Mounier Date: Tue, 14 May 2013 11:21:57 +0200 Subject: [PATCH] Work on worldmap, better svg + new data definition --- demo/moulinrouge/tests.py | 12 +++++----- pygal/css/style.css | 27 ++++++++-------------- pygal/graph/graph.py | 3 ++- pygal/graph/worldmap.py | 48 +++++++++++++++++++++++++++------------ pygal/graph/xy.py | 1 + pygal/style.py | 1 - pygal/util.py | 3 +-- 7 files changed, 54 insertions(+), 41 deletions(-) diff --git a/demo/moulinrouge/tests.py b/demo/moulinrouge/tests.py index d89c9cb..03b792f 100644 --- a/demo/moulinrouge/tests.py +++ b/demo/moulinrouge/tests.py @@ -167,7 +167,7 @@ def get_test_routes(app): @app.route('/test/logarithmic/') 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()) diff --git a/pygal/css/style.css b/pygal/css/style.css index 5571457..1693091 100644 --- a/pygal/css/style.css +++ b/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 }} + diff --git a/pygal/graph/graph.py b/pygal/graph/graph.py index 10c926e..11cd040 100644 --- a/pygal/graph/graph.py +++ b/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 diff --git a/pygal/graph/worldmap.py b/pygal/graph/worldmap.py index 6fdbcb6..d01eba1 100644 --- a/pygal/graph/worldmap.py +++ b/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) diff --git a/pygal/graph/xy.py b/pygal/graph/xy.py index 27173c6..53ece0a 100644 --- a/pygal/graph/xy.py +++ b/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): diff --git a/pygal/style.py b/pygal/style.py index 633a144..2611566 100644 --- a/pygal/style.py +++ b/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): diff --git a/pygal/util.py b/pygal/util.py index 631894b..db80148 100644 --- a/pygal/util.py +++ b/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__'):