{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"deletable": true,
"editable": true
},
"source": [
"# Tutorial - Drawing Interactive Diagrams with Dual Canvases \n",
"\n",
"This tutorial explains how to use the `dual_canvas_helper` jQuery plugin to implement\n",
"diagrams that respond to mouse events. The tutorial explains how to create the diagrams\n",
"as \"standalone pure Javascript\" which can be embedded in any HTML page and also shows\n",
"how to implement the diagrams inside a Jupyter IPython notebook.\n",
"\n",
"The `dual canvas` implementation can be used to develop \n",
"complex interactive visualizations such as the \n",
"[rectangles proof of concept](./rectangles.ipynb) which presents\n",
"a two category bar chart visualization supporting animated repositioning\n",
"and mouse over and drag interactions.\n",
"\n",
"
\n",
"\n",
"The tutorial is intended for programmers who have some knowledge of Javascript, Python\n",
"Jupyter, and HTML 5 libraries such as jQuery. The tutorial also makes use of\n",
"[proxy widget features](https://github.com/AaronWatters/jp_proxy_widget) without\n",
"explaining them in great detail -- please see the proxy widget tutorial for additional\n",
"discussion.\n",
"\n",
"The dual canvas implementation is a `jQueryUI` plugin which is built using `jQuery`\n",
"and some other plugin functionality. It requires several Javascript libraries\n",
"to be loaded.\n",
"\n",
"- `jQuery`,\n",
"- `jQueryUI`,\n",
"- `js/canvas_2d_widget_helper.js` -- the single canvas `jQuery` plugin, and\n",
"- `js/dual_canvas_helper.js` -- the dual canvas `jQuery` plugin.\n",
"\n",
"The Python wrapper `dual_canvas.py` makes the dual canvas conveniently available\n",
"as IPython widgets, and it provides a convenience function for loading the\n",
"required javascript libraries: `dual_canvas.load_requirements()`. These requirements\n",
"are loaded automagically by the `jp_doodle.dual_canvas.DualCanvasWidget` wrapper widget.\n",
"\n",
"Below we use `jp_proxy_widget.JSProxyWidget` directly instead of `DualCanvasWidget`\n",
"in order to show code fragments that can also run as stand alone Javascript, and that\n",
"is why we load the requirements explicitly in the next cell."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true
},
"outputs": [],
"source": [
"from jp_doodle import dual_canvas\n",
"dual_canvas.load_requirements()"
]
},
{
"cell_type": "markdown",
"metadata": {
"deletable": true,
"editable": true
},
"source": [
"# Drawing objects\n",
"\n",
"The `dual_canvas_helper` Plugin attaches a factory function to\n",
"jQuery elements `element.dual_canvas_helper(config)` which creates\n",
"an HTML canvas area associated with the element and attached as a child\n",
"of the element. Methods attached to the element like `element.rect({...})`\n",
"draw shapes onto the drawing area.\n",
"\n",
"Below we attach a canvas to a `jp_proxy_widget` IPython widget and\n",
"draw a number of objects onto the canvas using Javascript."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"deletable": true,
"editable": true
},
"outputs": [],
"source": [
"from IPython.display import HTML, display\n",
"import jp_proxy_widget\n",
"\n",
"# Create a proxy widget to contain the canvas.\n",
"canvas0 = jp_proxy_widget.JSProxyWidget()\n",
"\n",
"# Load javascript for the widget.\n",
"canvas0.js_init(\"\"\"\n",
"debugger;\n",
"// Empty the js_proxy jQuery element associated with the widget.\n",
"element.empty();\n",
"\n",
"// Attach an information div to the element to display event feedback.\n",
"var info_area = $(\"