{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# SVG Tooltip\n\nThis example shows how to create a tooltip that will show up when\nhovering over a matplotlib patch.\n\nAlthough it is possible to create the tooltip from CSS or javascript,\nhere we create it in matplotlib and simply toggle its visibility on\nwhen hovering over the patch. This approach provides total control over\nthe tooltip placement and appearance, at the expense of more code up\nfront.\n\nThe alternative approach would be to put the tooltip content in ``title``\nattributes of SVG objects. Then, using an existing js/CSS library, it\nwould be relatively straightforward to create the tooltip in the\nbrowser. The content would be dictated by the ``title`` attribute, and\nthe appearance by the CSS.\n\n\n:author: David Huard\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "from io import BytesIO\nimport xml.etree.ElementTree as ET\n\nimport matplotlib.pyplot as plt\n\nET.register_namespace(\"\", \"http://www.w3.org/2000/svg\")\n\nfig, ax = plt.subplots()\n\n# Create patches to which tooltips will be assigned.\nrect1 = plt.Rectangle((10, -20), 10, 5, fc='blue')\nrect2 = plt.Rectangle((-20, 15), 10, 5, fc='green')\n\nshapes = [rect1, rect2]\nlabels = ['This is a blue rectangle.', 'This is a green rectangle']\n\nfor i, (item, label) in enumerate(zip(shapes, labels)):\n    patch = ax.add_patch(item)\n    annotate = ax.annotate(labels[i], xy=item.get_xy(), xytext=(0, 0),\n                           textcoords='offset points', color='w', ha='center',\n                           fontsize=8, bbox=dict(boxstyle='round, pad=.5',\n                                                 fc=(.1, .1, .1, .92),\n                                                 ec=(1., 1., 1.), lw=1,\n                                                 zorder=1))\n\n    ax.add_patch(patch)\n    patch.set_gid(f'mypatch_{i:03d}')\n    annotate.set_gid(f'mytooltip_{i:03d}')\n\n# Save the figure in a fake file object\nax.set_xlim(-30, 30)\nax.set_ylim(-30, 30)\nax.set_aspect('equal')\n\nf = BytesIO()\nplt.savefig(f, format=\"svg\")\n\n# --- Add interactivity ---\n\n# Create XML tree from the SVG file.\ntree, xmlid = ET.XMLID(f.getvalue())\ntree.set('onload', 'init(event)')\n\nfor i in shapes:\n    # Get the index of the shape\n    index = shapes.index(i)\n    # Hide the tooltips\n    tooltip = xmlid[f'mytooltip_{index:03d}']\n    tooltip.set('visibility', 'hidden')\n    # Assign onmouseover and onmouseout callbacks to patches.\n    mypatch = xmlid[f'mypatch_{index:03d}']\n    mypatch.set('onmouseover', \"ShowTooltip(this)\")\n    mypatch.set('onmouseout', \"HideTooltip(this)\")\n\n# This is the script defining the ShowTooltip and HideTooltip functions.\nscript = \"\"\"\n    <script type=\"text/ecmascript\">\n    <![CDATA[\n\n    function init(event) {\n        if ( window.svgDocument == null ) {\n            svgDocument = event.target.ownerDocument;\n            }\n        }\n\n    function ShowTooltip(obj) {\n        var cur = obj.id.split(\"_\")[1];\n        var tip = svgDocument.getElementById('mytooltip_' + cur);\n        tip.setAttribute('visibility', \"visible\")\n        }\n\n    function HideTooltip(obj) {\n        var cur = obj.id.split(\"_\")[1];\n        var tip = svgDocument.getElementById('mytooltip_' + cur);\n        tip.setAttribute('visibility', \"hidden\")\n        }\n\n    ]]>\n    </script>\n    \"\"\"\n\n# Insert the script at the top of the file and save it.\ntree.insert(0, ET.XML(script))\nET.ElementTree(tree).write('svg_tooltip.svg')"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.14.6"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}