-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Expand file tree
/
Copy pathpatheffects_guide.py
More file actions
119 lines (102 loc) · 5.1 KB
/
patheffects_guide.py
File metadata and controls
119 lines (102 loc) · 5.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
"""
==================
Path effects guide
==================
Defining paths that objects follow on a canvas.
.. py:currentmodule:: matplotlib.patheffects
Matplotlib's :mod:`~matplotlib.patheffects` module provides functionality to
apply a multiple draw stage to any Artist which can be rendered via a
:class:`~matplotlib.path.Path`.
Artists which can have a path effect applied to them include :class:`~matplotlib.patches.Patch`,
:class:`~matplotlib.lines.Line2D`, :class:`~matplotlib.collections.Collection` and even
:class:`~matplotlib.text.Text`. Each artist's path effects can be controlled via the
``set_path_effects`` method (:class:`~matplotlib.artist.Artist.set_path_effects`), which takes
an iterable of :class:`AbstractPathEffect` instances.
The simplest path effect is the :class:`Normal` effect, which simply
draws the artist without any effect:
"""
import matplotlib.pyplot as plt
import matplotlib.patheffects as path_effects
fig = plt.figure(figsize=(5, 1.5))
text = fig.text(0.5, 0.5, 'Hello path effects world!\nThis is the normal '
'path effect.\nPretty dull, huh?',
ha='center', va='center', size=20)
text.set_path_effects([path_effects.Normal()])
plt.show()
###############################################################################
# Whilst the plot doesn't look any different to what you would expect without any path
# effects, the drawing of the text now been changed to use the path effects
# framework, opening up the possibilities for more interesting examples.
#
# Adding a shadow
# ---------------
#
# A far more interesting path effect than :class:`Normal` is the
# drop-shadow, which we can apply to any of our path based artists. The classes
# :class:`SimplePatchShadow` and
# :class:`SimpleLineShadow` do precisely this by drawing either a filled
# patch or a line patch below the original artist:
import matplotlib.patheffects as path_effects
text = plt.text(0.5, 0.5, 'Hello path effects world!',
path_effects=[path_effects.withSimplePatchShadow()])
plt.plot([0, 3, 2, 5], linewidth=5, color='blue',
path_effects=[path_effects.SimpleLineShadow(),
path_effects.Normal()])
plt.show()
###############################################################################
# Notice the two approaches to setting the path effects in this example. The
# first uses the ``with*`` classes to include the desired functionality automatically
# followed with the "normal" effect, whereas the latter explicitly defines the two path
# effects to draw.
#
# Making an artist stand out
# --------------------------
#
# One nice way of making artists visually stand out is to draw an outline in a bold
# color below the actual artist. The :class:`Stroke` path effect
# makes this a relatively simple task:
fig = plt.figure(figsize=(7, 1))
text = fig.text(0.5, 0.5, 'This text stands out because of\n'
'its black border.', color='white',
ha='center', va='center', size=30)
text.set_path_effects([path_effects.Stroke(linewidth=3, foreground='black'),
path_effects.Normal()])
plt.show()
###############################################################################
# It is important to note that this effect only works because we have drawn the text
# path twice; once with a thick black line, and then once with the original text
# path on top.
#
# You may have noticed that the keywords to :class:`Stroke` and
# :class:`SimplePatchShadow` and :class:`SimpleLineShadow` are not the usual Artist
# keywords (such as ``facecolor`` and ``edgecolor`` etc.). This is because with these
# path effects we are operating at lower level of matplotlib. In fact, the keywords
# which are accepted are those for a :class:`matplotlib.backend_bases.GraphicsContextBase`
# instance, which have been designed for making it easy to create new backends - and not
# for its user interface.
#
#
# Greater control of the path effect artist
# -----------------------------------------
#
# As already mentioned, some of the path effects operate at a lower level than most users
# will be used to, meaning that setting keywords such as ``facecolor`` and ``edgecolor``
# raise an AttributeError. Luckily there is a generic :class:`PathPatchEffect` path effect
# which creates a :class:`~matplotlib.patches.PathPatch` class with the original path.
# The keywords to this effect are identical to those of :class:`~matplotlib.patches.PathPatch`:
fig = plt.figure(figsize=(8, 1))
t = fig.text(0.02, 0.5, 'Hatch shadow', fontsize=75, weight=1000, va='center')
t.set_path_effects([path_effects.PathPatchEffect(offset=(4, -4), hatch='xxxx',
facecolor='gray'),
path_effects.PathPatchEffect(edgecolor='white', linewidth=1.1,
facecolor='black')])
plt.show()
###############################################################################
# ..
# Headings for future consideration:
#
# Implementing a custom path effect
# ---------------------------------
#
# What is going on under the hood
# --------------------------------