from matplotlib.figure import Figure
bins = ["A", "B", "C", "D", "E", "F"]
values = [3, 5, 8, 4, 2, 1]
cumul = [3, 8, 16, 20, 22, 23]
fig = Figure()
ax1, ax2 = fig.subplots(2, 1)
fig.suptitle("Répartition par appréciation")
ax1.bar(bins, values)
ax2.bar(bins, cumul)
fig.savefig("/tmp/test.png", format="png")
ou
with open("/tmp/test.png", 'wb') as f:
fig.savefig(f, format="png")
Formats supportés : png
(défaut), pdf
, svg
...
La classe io.BytesIO
permet de créer un fichier virtuel,
dont le contenu est stocké en mémoire,
et accessible à l'aide de la méthode getvalue
.
from io import BytesIO
b = BytesIO()
b.write(b"hello")
b.write(b" world")
print(b.getvalue())
# affiche b'hello world'
@app.route("/foo/<bar>/baz.png")
def example_matplotlib(bar):
data = make_data_from(bar) # requête SQL ou autre...
fig = Figure()
# ... création du graphique à partir de data ...
b = BytesIO()
fig.savefig(b, format="png")
resp = make_response(b.getvalue())
resp.headers['content-type'] = 'image/png'
return resp
Indice
Contrairement aux images raster comme PNG, qui sont discrétisées en pixels, les images vectorielles décrivent des formes mathématiques, qui peuvent donc être redimensionnées à volonté, sans perte de qualité.
<svg viewBox="-50 -50 100 100">
<circle cx="0" cy="0" r="40" style="fill:red" />
<rect x="-27.5" y="-7.5" width="55" height="15"
style="fill:white" />
</svg>
svg
§Elle contient tous les autres éléments SVG.
L'attribut viewBox
définit la zone affichable :
- x minimum (bord gauche)
- y minimum (bord haut)
- largeur
- hauteur
La taille réelle est fixée
- soit par CSS,
- soit par des attributs
«idth
etheight
directement dans la balisesvg
.
circle
§Elle décrit un cercle.
Elle utilise les attributs suivants :
cx
: abscisse du centrecy
: ordonnée du centrer
: rayon
Important
En SVG, les balises sans contenue doivent être explicitement fermée,
en les terminant par />
.
rect
§Elle décrit un rectangle.
Elle utilise les attributs suivants :
x
: abscisse du coin supérieur gauchey
: ordonnée du coin supérieur gauchewidth
: largeurheight
: hauteur
Attributs optionnels:
rx
: rayon horizontal des coinsry
: rayon vertical des coins (si différent derx
)
rect
§<svg viewBox="0 0 100 100">
<rect x="10" y="10" width="80" height="40" rx="10"
style="fill:teal"/>
<rect x="10" y="55" width="80" height="40" rx="20" ry="10"
style="fill:orange"/>
</svg>
line
§Elle décrit une ligne.
Elle utilise les attributs suivants :
x1
: abscisse du premier pointy1
: ordonnée du premier pointx2
: abscisse du second pointy2
: ordonnée du second point
rect
§<svg viewBox="0 0 100 100">
<line x1="10" y1="10" x2="50" y2="10" style="stroke:black"/>
<line x1="10" y1="20" x2="60" y2="30" style="stroke:black"/>
<line x1="10" y1="30" x2="80" y2="50" style="stroke:black"/>
</svg>
stroke
: couleur du trait/contourfill
: couleur de remplissagestroke-width
: largeur du traitstroke-dasharray
: largeurs des pointillésCette liste n'est pas exhaustive.
Ces attributs peuvent être spécifiés
style
, oucircle { stroke-width: 5 }
.foo { stroke: blue; fill: red }
.bar { stroke: green; fill: yellow }
<svg viewBow="0 0 200 100">
<circle cx="50" cy="50" r="45" class="foo" />
<circle cx="150" cy="50" r="45" class="bar" />
</svg>
CSS permet de plus d'ajouter un peu d'interactivité,
notamment avec la pseudo-classe CSS :hover
(documentation).
<svg viewBox="0 0 100 100">
<a href="http://champin.net/">
<rect x="10" y="10" width="80" height="40" rx="10"
style="fill:teal"/></a>
<a href="http://www.univ-lyon1.fr/">
<rect x="10" y="55" width="80" height="40" rx="20" ry="10"
style="fill:orange"/></a>
</svg>
matplotlib
§matplotlib
permet de générer facilement des graphiques complexes.img
mais pas directement dans le HTML,Les templates Jinja2 peuvent être utilisés pour générer du SVG.
Il sera cependant nécessaire de leur fournir des données « pré-traitées », dans lesquels les calculs géométriques compliqués ont été fait au préalable en Python.
Note
Les boucles {% for ... %}
peuvent être utilisée autour d'un ensemble de balise,
mais également à l'intérieur d'un attribut
(utile pour polyline
ou path
).
<svg viewBox="-10 -10 130 110">
<polyline points="0,90 0,0 110,0"/>
<path d="M 25,0 V -3 M 50,0 V -3 M 75,0 V -3 M 100,0 V -3"/>
<a href="#A">
<rect x="0" y="5" width="40" height="20"/>
<text x="0" y="5" dx="5" dy="12" text-anchor="middle">A</text></a>
<a href="#B">
<rect x="0" y="35" width="73" height="20" fill="teal"/>
<text x="0" y="35" dx="5" dy="12" text-anchor="middle">B</text></a>
<a href="#C">
<rect x="0" y="65" width="42" height="20" fill="teal"/>
<text x="0" y="65" dx="5" dy="12">C</text></a>
</svg>