Skip to content

Background images for plots #219

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions pygal/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
from pygal.style import Style, DefaultStyle
from pygal.interpolate import INTERPOLATIONS


CONFIG_ITEMS = []


Expand Down Expand Up @@ -170,7 +169,7 @@ class Config(CommonConfig):
DefaultStyle, Style, "Style", "Style holding values injected in css")

css = Key(
('style.css', 'graph.css'), list, "Style",
("!pygal.css.style_css", "!pygal.css.graph_css"), list, "Style",
"List of css file",
"It can be an absolute file path or an external link",
str)
Expand Down Expand Up @@ -428,6 +427,10 @@ class Config(CommonConfig):
"Don't prefix css")

inverse_y_axis = Key(False, bool, "Misc", "Inverse Y axis direction")

background_image = Key(None, str, "Misc", "Provide an optional background image to the plot")

preserve_aspect = Key(False, bool, "Misc", "Preserve aspect ratio")


class SerieConfig(CommonConfig):
Expand Down
Empty file added pygal/css/__init__.py
Empty file.
2 changes: 2 additions & 0 deletions pygal/css/base.css → pygal/css/base_css.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
data = """\
/*
* This file is part of pygal
*
Expand Down Expand Up @@ -55,3 +56,4 @@
{{ id }}text.no_data {
font-size: {{ font_sizes.no_data }};
}
"""
2 changes: 2 additions & 0 deletions pygal/css/graph.css → pygal/css/graph_css.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
data="""\
/*
* This file is part of pygal
*
Expand Down Expand Up @@ -126,3 +127,4 @@
{{ id }}.tooltip text tspan.label {
fill-opacity: .8;
}
"""
2 changes: 2 additions & 0 deletions pygal/css/style.css → pygal/css/style_css.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
data="""\
/*
* This file is part of pygal
*
Expand Down Expand Up @@ -139,3 +140,4 @@
{{ colors }}


"""
2 changes: 1 addition & 1 deletion pygal/graph/base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
# This file is part of pygal
#
# A python svg graph plotting library
Expand Down
14 changes: 2 additions & 12 deletions pygal/graph/frenchmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,7 @@
'06': u("Mayotte")
}


with open(os.path.join(
os.path.dirname(__file__), 'maps',
'fr.departments.svg')) as file:
DPT_MAP = file.read()

from .maps.fr_departments_svg import data as DPT_MAP

class IntCodeMixin(object):
def adapt_code(self, area_code):
Expand All @@ -194,12 +189,7 @@ class FrenchMapDepartments(IntCodeMixin, BaseMap):
kind = 'departement'
svg_map = DPT_MAP


with open(os.path.join(
os.path.dirname(__file__), 'maps',
'fr.regions.svg')) as file:
REG_MAP = file.read()

from .maps.fr_regions_svg import data as REG_MAP

class FrenchMapRegions(IntCodeMixin, BaseMap):
"""French regions map"""
Expand Down
25 changes: 24 additions & 1 deletion pygal/graph/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ def _set_view(self):
self.view = view_class(
self.width - self.margin_box.x,
self.height - self.margin_box.y,
self._box)
self._box,
self.preserve_aspect)

def _make_graph(self):
"""Init common graph svg structure"""
Expand All @@ -87,6 +88,28 @@ def _make_graph(self):
x=0, y=0,
width=self.view.width,
height=self.view.height)
if not self.background_image is None:
corners = list(map(self.view, ( (self._box.xmin,self._box.ymin), (self._box.xmax,self._box.ymax) ) ))

x0 = min(corners[0][0], corners[1][0])
y0 = min(corners[0][1], corners[1][1])
x1 = max(corners[0][0], corners[1][0])
y1 = max(corners[0][1], corners[1][1])
w = x1-x0
h = y1-y0
x0 += self._box.margin*w
y0 += self._box.margin*h
w -= self._box.margin*2*w
h -= self._box.margin*2*h
self.nodes['bgimage'] = self.svg.node(
self.nodes['plot'],
tag='image',
attrib={'xlink:href' : self.background_image},
x=x0,
y=y0,
width=w,
height=h,
preserveAspectRatio="none")
self.nodes['title'] = self.svg.node(
self.nodes['graph'],
class_="titles")
Expand Down
Empty file added pygal/graph/maps/__init__.py
Empty file.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
data = """\
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<g id="cantons" transform="translate(-265.0,-825.0) matrix(0.53050535,0,0,0.53379421,130.8741,392.31231)">
<g class="zkt-zh canton map-element"><path d="m 950.10063,1055.077 0,-1.8258 c 0,0 -0.75,-2.1909 -0.75,-3.4081 0,-1.2172 -1,-3.1647 -1,-3.1647 l -0.5,-5.1122 -3.75,-3.6516 4,0.7303 1.75,-1.9475 2.75,0.2434 1.5,-2.4344 2.25,-0.7303 0.25,-3.4081 c 0,0 1.25,-2.191 2.25,-2.9213 1,-0.7303 2.5,-2.1909 3.25,-3.1647 0.75,-0.9737 0.75,-3.895 0.75,-3.895 0,0 -2,2.1909 -4,2.4344 -2,0.2434 -4.5,0.9737 -5.5,1.2172 -1,0.2434 -3,0 -2,-1.9475 1,-1.9475 1.5,-2.6779 0,-4.1385 -1.5,-1.4606 -2.25,-1.7041 -1.75,-3.6516 0.5,-1.9475 0.75,-3.895 0.75,-3.895 l -0.5,-3.6516 -3.25,-3.895 -0.25,-6.32941 -2.75,-0.4869 -1,-1.704 -3.75,0 0,-2.191 3.5,-0.4869 0.75,-3.6515 1,-1.7041 1.25,-2.4344 -4.25,-1.4606 2.25,-3.1647 -0.75,-3.1647 1.5,-2.191 -1,-3.4081 -3,-0.4869 -1.25,-3.895 2.25,-1.2172 -0.5,-3.6516 -2.75,0.2435 -0.75,-5.5991 1,-1.9475 -1.25,-2.6779 1.5,-2.6778 4,0 0.5,-3.1647 1.25,-2.9212 2.75,1.704 0.75,-3.1647 1.75,-0.4869 0,-3.1647 2.25,-1.9475 1.75,-0.7303 -0.75,-2.9212 0.75,-2.9213 1.25,-2.6778 1.6133,-3.1761 3e-4,0 0.252,0.078 0.7519,-0.061 2.0806,-1.0752 3.0454,-0.2813 4.8438,-1.2058 3.2661,-0.9595 0.7309,-0.2106 1.9268,-0.5694 -0.9463,-1.2212 -4.9253,1.3701 -2.7231,-4.3646 3.4267,-2.0552 2.1109,-4.0217 7.2964,-1.7131 2.1108,-3.083 1.4068,-2.6516 4.8339,0.2539 0.7041,2.3977 3.4263,0.3426 4.5737,4.1107 -3.3062,5.6322 -1.8985,2.8917 -3.4268,1.3703 -0.7036,3.4255 1.7588,2.0552 3.0752,6.0774 1.416,-1.1268 0.25,-2.9213 0.5,-1.7041 2.5,-2.9212 1.75,-3.4082 0.75,-1.9475 0.2795,0.2051 1.2251,-1.3959 0.1621,-1.8634 2.18997,-3.9616 0.3882,-1.6926 -2.32037,-9.1263 1.05767,-4.1742 4.7417,-3.6815 -1.4062,-3.4141 -0.049,-0.6238 -0.082,-0.9671 -10e-5,-10e-5 1.0928,-1.4768 1,-2.5561 2,-1.9475 0.875,-4.1385 2.125,-1.8258 4.375,0.1218 2.875,0.852 3.75,3.895 1.625,-0.4868 -1.375,6.0859 3,1.9476 0.5,4.8687 2,3.6516 3.75,0.9738 1.25,1.704 3.5,0.4869 2.75,-0.4869 4.5,0.9738 3.25,-0.9738 2.5,-2.6778 3.25,0 2.25,-2.4344 1,-3.895 4,0 0.5,5.3557 4.5,1.4606 1.25,3.1647 -0.5,1.7041 -3,2.9212 c 0,0 -0.5,0.4869 -0.5,2.9213 0,2.4344 -2.75,3.1647 -2.75,3.1647 l -0.25,5.1122 -3.5,-0.9738 -0.25,-2.4343 -7.25,-3.6516 -3.75,-0.9738 -2,6.086 2.75,1.9475 -0.75,3.4081 4,0 11.25,4.6254 1.25,4.1384 7.5,-0.7303 3.75,4.3819 -2.5,1.7041 -2.75,0.7303 1.75,4.6253 2.25,4.8688 7,0 2.25,1.7041 5.5,0.4868 0,9.2507 -1.75,4.1385 1.25,4.1384 -3.25,0.9738 -0.25,2.9212 2.75,2.191 1.75,4.8687 2,1.2172 0.25,1.9475 -1,1.9476 1.5,2.4343 5,0.4869 0,1.9475 -5.25,0.2435 2,3.6515 -0.75,3.4082 -2,3.1647 0.25,2.1909 3.75,0.7303 2.25,2.4344 4,2.4344 -0.25,2.92131 3,2.1909 2,7.3032 2.5,0 1.75,2.9213 -1,3.1647 2.25,0.7303 -0.75,4.1384 2.5,2.9213 -3.75,5.5991 -4,0.4869 -1.5,2.1909 -0.75,2.9213 -3.75,1.4606 1,3.4081 2.5,0.4869 -3.5,7.79 -5.75,1.7041 -7.25,0.9738 -3.25,0.2434 -1.25,2.6778 -4.75,0.9738 -1.5,-3.1647 -2.25,1.9475 -4.5,-2.191 -4.75,1.4607 -4.084,2.4508 -1.166,6.313 -4e-4,0 -14.75,0.9737 -5.251,6.3099 -4.499,4.6449 -3.75,2.6778 -1.25,2.6778 0.5,3.895 2.25,1.4607 0.5,2.1909 4e-4,0 -3.5,0.7303 -2.5,1.7041 -3.5,-1.2172 0.25,-2.9213 -3,-0.9737 -2,1.2172 -1.75,-1.2172 -3.75,-0.7303 1.5,-2.4344 -2.5,-3.895 -1.5,-5.5991 -3.5,0 0.25,-1.7041 -1.25,-1.7041 -3.75007,0.7303 0,-2.9212 -7.5,-1.9475 -5.5,-0.2435 -1.25,1.9475 -2.5,-1.2171 -2.75,0.2434 -0.75,1.9475 -2.25,1.2172 -2.75,0 -2.75,1.2172 -1.75,-0.2435 -3.5,-2.6778 -3.75,-1.2172 -1.75,-2.4344 -5.5,0.4869 -1.25,-3.895 -0.5,-2.4344 -2.25,-3.5298 z" id="kt-zh"/></g>
Expand Down Expand Up @@ -88,4 +89,4 @@
<polygon id="polygon151-6" style="fill:#0978ab;stroke:#0978ab;stroke-width:1.01338696;" points="361.27954,499.90723 359.76001,500.64014 356.82764,504.27197 357.33179,507.26074 356.56812,508.5332 356.32373,511.18994 356.56812,514.47705 358.73657,523.90381 358.41602,526.93799 359.19482,528.03906 358.69849,530.98193 357.00317,529.83691 355.73584,529.99756 356.04126,526.7666 354.94922,510.97266 355.30811,506.89404 353.94116,506.99805 352.76538,508.60059 352.6355,507.66162 355.34644,499.90723 357.36206,498.01807 357.7439,496.48291 355.98755,496.00146 355.29297,494.71924 355.28516,492.64648 354.50635,491.54688 356.03345,489.11816 357.57593,487.98389 359.74463,486.39209 359.74463,486.39209 359.88965,487.60645 359.06494,489.53027 357.37744,490.56201 357.18652,492.26904 360.27905,497.97217 361.72998,497.28516 362.95923,496.7124 361.59253,499.3125 " transform="matrix(1,0,0,0.9737543,234.60453,792.53506)"/>
</g>
</svg>

"""
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
data="""\
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2000 1898">
<g id="departements" transform="translate(-42.932808,96.039162)">
<g class="z95 departement map-element">
Expand Down Expand Up @@ -326,3 +327,4 @@
</g>
</g>
</svg>
"""
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
data="""\
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 2000 1898">
<g id="regions" transform="translate(-42.932808,96.039162)">
<g class="a94 region map-element">
Expand Down Expand Up @@ -89,3 +90,4 @@
</g>
</g>
</svg>
"""
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
data="""\
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 2475 1388">
<g id="countries">
<g class="ad country map-element">
Expand Down Expand Up @@ -2408,3 +2409,4 @@
</g>
</g>
</svg>
"""
7 changes: 1 addition & 6 deletions pygal/graph/swissmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,7 @@
'kt-ge': u("Genf"),
}


with open(os.path.join(
os.path.dirname(__file__), 'maps',
'ch.cantons.svg')) as file:
CNT_MAP = file.read()

from .maps.ch_cantons_svg import data as CNT_MAP

class SwissMapCantons(BaseMap):
"""Swiss Cantons map"""
Expand Down
7 changes: 1 addition & 6 deletions pygal/graph/worldmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,7 @@
from pygal.i18n import COUNTRIES, SUPRANATIONAL
import os


with open(os.path.join(
os.path.dirname(__file__), 'maps',
'worldmap.svg')) as file:
WORLD_MAP = file.read()

from .maps.worldmap_svg import data as WORLD_MAP

class Worldmap(BaseMap):
"""Worldmap graph"""
Expand Down
34 changes: 21 additions & 13 deletions pygal/svg.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@
import io
import os
import json
import importlib
from datetime import date, datetime
from numbers import Number
from math import cos, sin, pi
from pygal.util import template, coord_format, minify_css
from pygal import __version__
from pygal.css import base_css


class Svg(object):
Expand Down Expand Up @@ -83,18 +85,25 @@ def add_styles(self):
"""Add the css to the svg"""
colors = self.graph.style.get_colors(self.id)
all_css = []
for css in ['base.css'] + list(self.graph.css):
if '://' in css:
for css in [base_css] + list(self.graph.css):
if type(css) == str and '://' in css:
self.processing_instructions.append(
etree.PI(
u('xml-stylesheet'), u('href="%s"' % css)))
else:
if css.startswith('inline:'):
if type(css) == str and css.startswith('inline:'):
css_text = css[len('inline:'):]
else:
if not os.path.exists(css):
css = os.path.join(
os.path.dirname(__file__), 'css', css)
if type(css) == str and css.startswith("!"):
css_raw = importlib.import_module(css[1:]).data
elif type(css) == str:
if not os.path.exists(css):
css = os.path.join(
os.path.dirname(__file__), 'css', css)
with io.open(css, encoding='utf-8') as f:
css_raw = f.read()
else:
css_raw = css.data

class FontSizes(object):
"""Container for font sizes"""
Expand All @@ -106,13 +115,12 @@ class FontSizes(object):
name.replace('_font_size', ''),
('%dpx' % getattr(self.graph, name)))

with io.open(css, encoding='utf-8') as f:
css_text = template(
f.read(),
style=self.graph.style,
colors=colors,
font_sizes=fs,
id=self.id)
css_text = template(
css_raw,
style=self.graph.style,
colors=colors,
font_sizes=fs,
id=self.id)
if not self.graph.pretty_print:
css_text = minify_css(css_text)
all_css.append(css_text)
Expand Down
Loading