|
3 | 3 |
|
4 | 4 | """
|
5 | 5 | Demonstrate how to create an interactive histogram, in which bars
|
6 |
| -are hidden or shown by cliking on legend markers. |
| 6 | +are hidden or shown by cliking on legend markers. |
7 | 7 |
|
8 |
| -The interactivity is encoded in ecmascript (javascript) and inserted in |
9 |
| -the SVG code in a post-processing step. To render the image, open it in |
10 |
| -a web browser. SVG is supported in most web browsers used by Linux and |
11 |
| -OSX users. Windows IE9 supports SVG, but earlier versions do not. |
| 8 | +The interactivity is encoded in ecmascript (javascript) and inserted in |
| 9 | +the SVG code in a post-processing step. To render the image, open it in |
| 10 | +a web browser. SVG is supported in most web browsers used by Linux and |
| 11 | +OSX users. Windows IE9 supports SVG, but earlier versions do not. |
12 | 12 |
|
13 | 13 | Notes
|
14 | 14 | -----
|
15 | 15 | The matplotlib backend lets us assign ids to each object. This is the
|
16 |
| -mechanism used here to relate matplotlib objects created in python and |
| 16 | +mechanism used here to relate matplotlib objects created in python and |
17 | 17 | the corresponding SVG constructs that are parsed in the second step.
|
18 |
| -While flexible, ids are cumbersome to use for large collection of |
| 18 | +While flexible, ids are cumbersome to use for large collection of |
19 | 19 | objects. Two mechanisms could be used to simplify things:
|
20 | 20 | * systematic grouping of objects into SVG <g> tags,
|
21 | 21 | * assingning classes to each SVG object according to its origin.
|
22 |
| - |
23 |
| -For example, instead of modifying the properties of each individual bar, |
| 22 | +
|
| 23 | +For example, instead of modifying the properties of each individual bar, |
24 | 24 | the bars from the `hist` function could either be grouped in
|
25 |
| -a PatchCollection, or be assigned a class="hist_##" attribute. |
| 25 | +a PatchCollection, or be assigned a class="hist_##" attribute. |
26 | 26 |
|
27 | 27 | CSS could also be used more extensively to replace repetitive markup
|
28 |
| -troughout the generated SVG. |
| 28 | +troughout the generated SVG. |
29 | 29 |
|
30 | 30 | __author__="david.huard@gmail.com"
|
31 | 31 |
|
|
40 | 40 |
|
41 | 41 | plt.rcParams['svg.embed_char_paths'] = 'none'
|
42 | 42 |
|
43 |
| -# Apparently, this `register_namespace` method works only with |
| 43 | +# Apparently, this `register_namespace` method works only with |
44 | 44 | # python 2.7 and up and is necessary to avoid garbling the XML name
|
45 | 45 | # space with ns0.
|
46 | 46 | ET.register_namespace("", "http://www.w3.org/2000/svg")
|
|
54 | 54 | H = plt.hist([r, r1], label=labels)
|
55 | 55 | containers = H[-1]
|
56 | 56 | leg = plt.legend(frameon=False)
|
57 |
| -plt.title("""From a web browser, click on the legend |
| 57 | +plt.title("""From a web browser, click on the legend |
58 | 58 | marker to toggle the corresponding histogram.""")
|
59 | 59 |
|
60 | 60 |
|
61 |
| -# --- Add ids to the svg objects we'll modify |
| 61 | +# --- Add ids to the svg objects we'll modify |
62 | 62 |
|
63 | 63 | hist_patches = {}
|
64 | 64 | for ic, c in enumerate(containers):
|
|
67 | 67 | element.set_gid('hist_%d_patch_%d' % (ic, il))
|
68 | 68 | hist_patches['hist_%d' %ic].append('hist_%d_patch_%d' % (ic, il))
|
69 | 69 |
|
70 |
| -# Set ids for the legend patches |
| 70 | +# Set ids for the legend patches |
71 | 71 | for i, t in enumerate(leg.get_patches()):
|
72 | 72 | t.set_gid('leg_patch_%d' % i)
|
73 | 73 |
|
|
85 | 85 |
|
86 | 86 | # --- Add interactivity ---
|
87 | 87 |
|
88 |
| -# Add attributes to the patch objects. |
| 88 | +# Add attributes to the patch objects. |
89 | 89 | for i, t in enumerate(leg.get_patches()):
|
90 | 90 | el = xmlid['leg_patch_%d' % i]
|
91 | 91 | el.set('cursor', 'pointer')
|
92 | 92 | el.set('onclick', "toggle_hist(this)")
|
93 | 93 |
|
94 |
| -# Add attributes to the text objects. |
| 94 | +# Add attributes to the text objects. |
95 | 95 | for i, t in enumerate(leg.get_texts()):
|
96 | 96 | el = xmlid['leg_text_%d' % i]
|
97 | 97 | el.set('cursor', 'pointer')
|
98 | 98 | el.set('onclick', "toggle_hist(this)")
|
99 | 99 |
|
100 |
| -# Create script defining the function `toggle_hist`. |
101 |
| -# We create a global variable `container` that stores the patches id |
102 |
| -# belonging to each histogram. Then a function "toggle_element" sets the |
| 100 | +# Create script defining the function `toggle_hist`. |
| 101 | +# We create a global variable `container` that stores the patches id |
| 102 | +# belonging to each histogram. Then a function "toggle_element" sets the |
103 | 103 | # visibility attribute of all patches of each histogram and the opacity
|
104 |
| -# of the marker itself. |
| 104 | +# of the marker itself. |
105 | 105 |
|
106 | 106 | script = """
|
107 | 107 | <script type="text/ecmascript">
|
108 | 108 | <![CDATA[
|
109 |
| -var container = %s |
| 109 | +var container = %s |
110 | 110 |
|
111 | 111 | function toggle(oid, attribute, values) {
|
112 |
| - /* Toggle the style attribute of an object between two values. |
113 |
| - |
| 112 | + /* Toggle the style attribute of an object between two values. |
| 113 | +
|
114 | 114 | Parameters
|
115 | 115 | ----------
|
116 | 116 | oid : str
|
|
122 | 122 | */
|
123 | 123 | var obj = document.getElementById(oid);
|
124 | 124 | var a = obj.style[attribute];
|
125 |
| - |
| 125 | +
|
126 | 126 | a = (a == values[0] || a == "") ? values[1] : values[0];
|
127 | 127 | obj.style[attribute] = a;
|
128 | 128 | }
|
129 | 129 |
|
130 | 130 | function toggle_hist(obj) {
|
131 |
| - |
| 131 | +
|
132 | 132 | var num = obj.id.slice(-1);
|
133 |
| - |
| 133 | +
|
134 | 134 | toggle('leg_patch_' + num, 'opacity', [1, 0.3]);
|
135 | 135 | toggle('leg_text_' + num, 'opacity', [1, 0.5]);
|
136 |
| - |
| 136 | +
|
137 | 137 | var names = container['hist_'+num]
|
138 |
| - |
| 138 | +
|
139 | 139 | for (var i=0; i < names.length; i++) {
|
140 | 140 | toggle(names[i], 'opacity', [1,0])
|
141 | 141 | };
|
|
146 | 146 |
|
147 | 147 | # Add a transition effect
|
148 | 148 | css = tree.getchildren()[0][0]
|
149 |
| -css.text = css.text + "g {-webkit-transition:opacity 0.4s ease-out;-moz-transition:opacity 0.4s ease-out;}" |
| 149 | +css.text = css.text + "g {-webkit-transition:opacity 0.4s ease-out;" + \ |
| 150 | + "-moz-transition:opacity 0.4s ease-out;}" |
150 | 151 |
|
151 | 152 | # Insert the script and save to file.
|
152 | 153 | tree.insert(0, ET.XML(script))
|
|
0 commit comments