|
| 1 | +""" |
| 2 | +SVG tooltip example |
| 3 | +=================== |
| 4 | +
|
| 5 | +This example shows how to create a tooltip that will show up when |
| 6 | +hovering over a matplotlib patch. |
| 7 | +
|
| 8 | +Although it is possible to create the tooltip from CSS or javascript, |
| 9 | +here we create it in matplotlib and simply toggle its visibility on |
| 10 | +when hovering over the patch. This approach provides total control over |
| 11 | +the tooltip placement and appearance, at the expense of more code up |
| 12 | +front. |
| 13 | +
|
| 14 | +The alternative approach would be to put the tooltip content in `title` |
| 15 | +atttributes of SVG objects. Then, using an existing js/CSS library, it |
| 16 | +would be relatively straightforward to create the tooltip in the |
| 17 | +browser. The content would be dictated by the `title` attribute, and |
| 18 | +the appearance by the CSS. |
| 19 | +
|
| 20 | +
|
| 21 | +:author: David Huard |
| 22 | +""" |
| 23 | + |
| 24 | + |
| 25 | +import matplotlib.pyplot as plt |
| 26 | +import xml.etree.ElementTree as ET |
| 27 | +from StringIO import StringIO |
| 28 | + |
| 29 | +ET.register_namespace("","http://www.w3.org/2000/svg") |
| 30 | + |
| 31 | +fig = plt.figure() |
| 32 | +ax = fig.add_subplot(111) |
| 33 | + |
| 34 | +# Create patches to which tooltips will be assigned. |
| 35 | +circle = plt.Circle((0,0), 5, fc='blue') |
| 36 | +rect = plt.Rectangle((-5, 10), 10, 5, fc='green') |
| 37 | + |
| 38 | +ax.add_patch(circle) |
| 39 | +ax.add_patch(rect) |
| 40 | + |
| 41 | +# Create the tooltips |
| 42 | +circle_tip = ax.annotate('This is a blue circle.', |
| 43 | + xy=(0,0), |
| 44 | + xytext=(30,-30), |
| 45 | + textcoords='offset points', |
| 46 | + color='w', |
| 47 | + ha='left', |
| 48 | + bbox=dict(boxstyle='round,pad=.5', fc=(.1,.1,.1,.92), ec=(1.,1.,1.), lw=1, zorder=1), |
| 49 | + ) |
| 50 | + |
| 51 | +rect_tip = ax.annotate('This is a green rectangle.', |
| 52 | + xy=(-5,10), |
| 53 | + xytext=(30,40), |
| 54 | + textcoords='offset points', |
| 55 | + color='w', |
| 56 | + ha='left', |
| 57 | + bbox=dict(boxstyle='round,pad=.5', fc=(.1,.1,.1,.92), ec=(1.,1.,1.), lw=1, zorder=1), |
| 58 | + ) |
| 59 | + |
| 60 | + |
| 61 | +# Set id for the patches |
| 62 | +for i, t in enumerate(ax.patches): |
| 63 | + t.set_gid('patch_%d'%i) |
| 64 | + |
| 65 | +# Set id for the annotations |
| 66 | +for i, t in enumerate(ax.texts): |
| 67 | + t.set_gid('tooltip_%d'%i) |
| 68 | + |
| 69 | + |
| 70 | +# Save the figure in a fake file object |
| 71 | +ax.set_xlim(-30, 30) |
| 72 | +ax.set_ylim(-30, 30) |
| 73 | +ax.set_aspect('equal') |
| 74 | + |
| 75 | +f = StringIO() |
| 76 | +plt.savefig(f, format="svg") |
| 77 | + |
| 78 | +# --- Add interactivity --- |
| 79 | + |
| 80 | +# Create XML tree from the SVG file. |
| 81 | +tree, xmlid = ET.XMLID(f.getvalue()) |
| 82 | +tree.set('onload', 'init(evt)') |
| 83 | + |
| 84 | +# Hide the tooltips |
| 85 | +for i, t in enumerate(ax.texts): |
| 86 | + el = xmlid['tooltip_%d'%i] |
| 87 | + el.set('visibility', 'hidden') |
| 88 | + |
| 89 | +# Assign onmouseover and onmouseout callbacks to patches. |
| 90 | +for i, t in enumerate(ax.patches): |
| 91 | + el = xmlid['patch_%d'%i] |
| 92 | + el.set('onmouseover', "ShowTooltip(this)") |
| 93 | + el.set('onmouseout', "HideTooltip(this)") |
| 94 | + |
| 95 | +# This is the script defining the ShowTooltip and HideTooltip functions. |
| 96 | +script = """ |
| 97 | + <script type="text/ecmascript"> |
| 98 | + <![CDATA[ |
| 99 | + |
| 100 | + function init(evt) { |
| 101 | + if ( window.svgDocument == null ) { |
| 102 | + svgDocument = evt.target.ownerDocument; |
| 103 | + } |
| 104 | + } |
| 105 | + |
| 106 | + function ShowTooltip(obj) { |
| 107 | + var cur = obj.id.slice(-1); |
| 108 | + |
| 109 | + var tip = svgDocument.getElementById('tooltip_' + cur); |
| 110 | + tip.setAttribute('visibility',"visible") |
| 111 | + } |
| 112 | + |
| 113 | + function HideTooltip(obj) { |
| 114 | + var cur = obj.id.slice(-1); |
| 115 | + var tip = svgDocument.getElementById('tooltip_' + cur); |
| 116 | + tip.setAttribute('visibility',"hidden") |
| 117 | + } |
| 118 | + |
| 119 | + ]]> |
| 120 | + </script> |
| 121 | + """ |
| 122 | + |
| 123 | +# Insert the script at the top of the file and save it. |
| 124 | +tree.insert(0, ET.XML(script)) |
| 125 | +ET.ElementTree(tree).write('svg_tooltip.svg') |
0 commit comments