Skip to content

Commit 783f608

Browse files
authored
Merge pull request #52 from martinRenou/example_plot_class
Add Handdrawing Notebook example
2 parents 0e9b6c6 + fc4f62e commit 783f608

File tree

6 files changed

+131
-17
lines changed

6 files changed

+131
-17
lines changed

docs/source/drawing_images.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ From an Image widget
66

77
You can draw from an `Image <https://ipywidgets.readthedocs.io/en/stable/examples/Widget%20List.html#Image>`_ widget directly, this is the less optimized solution but it works perfectly fine if you don't draw more than a hundred images at a time.
88

9-
- ``draw_image(image, x, y, width=None, height=None)``: Draw an ``image`` on the Canvas at the coordinates (``x``, ``y``) and scale it to (``width``, ``height``). The ``image`` must be an ``Image`` widget or another ``Canvas``.
9+
- ``draw_image(image, x=0, y=0, width=None, height=None)``: Draw an ``image`` on the Canvas at the coordinates (``x``, ``y``) and scale it to (``width``, ``height``). The ``image`` must be an ``Image`` widget or another ``Canvas``. If ``width``/``height`` is ``None``, the natural image ``width``/``height`` is used.
1010

1111
.. code:: Python
1212
@@ -51,7 +51,7 @@ From a NumPy array
5151

5252
You can directly draw a NumPy array of pixels on the ``Canvas``, it must be a 3-D array of integers and the last dimension must be 3 or 4 (rgb or rgba), with values going from ``0`` to ``225``.
5353

54-
- ``put_image_data(image_data, dx, dy)``: Draw an image on the Canvas. ``image_data`` should be a NumPy array containing the image to draw and ``dx`` and ``dy`` the pixel position where to draw (top left pixel of the image).
54+
- ``put_image_data(image_data, x=0, y=0)``: Draw an image on the Canvas. ``image_data`` should be a NumPy array containing the image to draw and ``x`` and ``y`` the pixel position where to draw (top left pixel of the image).
5555

5656
.. code:: python
5757

docs/source/events.rst

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
Interactions
22
============
33

4-
Using built-in events
4+
Built-in mouse events
55
---------------------
66

7-
The following built-in mouse events are supported: ``mouse_down``, ``mouse_move``, ``mouse_up`` and ``mouse_out``.
7+
The following built-in mouse events are supported: ``mouse_down``, ``mouse_move``, ``mouse_up`` and ``mouse_out``. You can define Python callback functions that will be called whenever those mouse events occur, using the ``on_mouse_down``, ``on_mouse_move``, ``on_mouse_up`` and ``on_mouse_out`` methods.
8+
9+
Those methods take a callback function as single argument, this callback function must take two positional arguments that are the ``x`` and ``y`` pixel coordinates where the mouse was during the event.
810

911
.. code:: Python
1012
@@ -23,8 +25,8 @@ The following built-in mouse events are supported: ``mouse_down``, ``mouse_move`
2325
.. note::
2426
Please open an issue or a Pull Request if you want more events to be supported by ipycanvas
2527

26-
Using ipyevents
27-
---------------
28+
ipyevents
29+
---------
2830

2931
If built-in events are not enough for your use case, you can use `ipyevents <https://github.com/mwcraig/ipyevents>`_ which provides mouse and keyboard events.
3032

examples/hand_drawing.ipynb

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"metadata": {},
7+
"outputs": [],
8+
"source": [
9+
"from ipywidgets import Image\n",
10+
"\n",
11+
"from ipywidgets import ColorPicker, IntSlider, link, AppLayout, HBox\n",
12+
"\n",
13+
"from ipycanvas import MultiCanvas, hold_canvas"
14+
]
15+
},
16+
{
17+
"cell_type": "code",
18+
"execution_count": null,
19+
"metadata": {},
20+
"outputs": [],
21+
"source": [
22+
"width = 500\n",
23+
"height = 500"
24+
]
25+
},
26+
{
27+
"cell_type": "code",
28+
"execution_count": null,
29+
"metadata": {},
30+
"outputs": [],
31+
"source": [
32+
"canvas = MultiCanvas(3, size=(width, height))\n",
33+
"\n",
34+
"image = Image.from_file('sprites/logo.png')\n",
35+
"\n",
36+
"background_layer = canvas[0]\n",
37+
"drawing_layer = canvas[1]\n",
38+
"interaction_layer = canvas[2]\n",
39+
"\n",
40+
"drawing = False\n",
41+
"start = None\n",
42+
"\n",
43+
"def draw_line(canvas, start, end):\n",
44+
" canvas.begin_path()\n",
45+
" canvas.move_to(start[0], start[1])\n",
46+
" canvas.line_to(end[0], end[1])\n",
47+
" canvas.stroke()\n",
48+
" canvas.close_path()\n",
49+
"\n",
50+
"def on_mouse_down(x, y):\n",
51+
" global drawing\n",
52+
" global start\n",
53+
"\n",
54+
" if not drawing:\n",
55+
" start = (x, y)\n",
56+
" else:\n",
57+
" with hold_canvas(canvas):\n",
58+
" draw_line(drawing_layer, start, (x, y))\n",
59+
"\n",
60+
" interaction_layer.clear()\n",
61+
"\n",
62+
" start = None\n",
63+
" \n",
64+
" drawing = not drawing\n",
65+
"\n",
66+
"def on_mouse_move(x, y):\n",
67+
" if not drawing:\n",
68+
" return\n",
69+
"\n",
70+
" with hold_canvas(canvas):\n",
71+
" interaction_layer.clear()\n",
72+
"\n",
73+
" draw_line(interaction_layer, start, (x, y))\n",
74+
"\n",
75+
"interaction_layer.on_mouse_down(on_mouse_down)\n",
76+
"interaction_layer.on_mouse_move(on_mouse_move)\n",
77+
"\n",
78+
"background_layer.draw_image(image, 0, 0, width, height)\n",
79+
"\n",
80+
"drawing_layer.stroke_style = '#749cb8'\n",
81+
"drawing_layer.line_width = 3\n",
82+
"interaction_layer.stroke_style = '#749cb8'\n",
83+
"interaction_layer.line_width = 3\n",
84+
"\n",
85+
"picker = ColorPicker(description='Color:', value='#749cb8')\n",
86+
"slider = IntSlider(description='Line width:', value=3, min=1, max=20)\n",
87+
"\n",
88+
"link((picker, 'value'), (drawing_layer, 'stroke_style'))\n",
89+
"link((picker, 'value'), (interaction_layer, 'stroke_style'))\n",
90+
"link((slider, 'value'), (drawing_layer, 'line_width'))\n",
91+
"link((slider, 'value'), (interaction_layer, 'line_width'))\n",
92+
"\n",
93+
"AppLayout(center=canvas, footer=HBox((picker, slider)))"
94+
]
95+
}
96+
],
97+
"metadata": {
98+
"kernelspec": {
99+
"display_name": "Python 3",
100+
"language": "python",
101+
"name": "python3"
102+
},
103+
"language_info": {
104+
"codemirror_mode": {
105+
"name": "ipython",
106+
"version": 3
107+
},
108+
"file_extension": ".py",
109+
"mimetype": "text/x-python",
110+
"name": "python",
111+
"nbconvert_exporter": "python",
112+
"pygments_lexer": "ipython3",
113+
"version": "3.7.3"
114+
}
115+
},
116+
"nbformat": 4,
117+
"nbformat_minor": 4
118+
}

examples/sprites.ipynb

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,7 @@
44
"cell_type": "markdown",
55
"metadata": {},
66
"source": [
7-
"# Displaying sprites on the Canvas\n",
8-
"\n",
9-
"Note that this notebook needs `pillow` for loading the sprite image:\n",
10-
"\n",
11-
"```\n",
12-
"$ pip install pillow\n",
13-
"```"
7+
"# Displaying sprites on the Canvas"
148
]
159
},
1610
{

examples/sprites/logo.png

72.4 KB
Loading

ipycanvas/canvas.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ def set_line_dash(self, segments):
377377
self._send_canvas_command('setLineDash', (self._line_dash, ))
378378

379379
# Image methods
380-
def draw_image(self, image, x, y, width=None, height=None):
380+
def draw_image(self, image, x=0, y=0, width=None, height=None):
381381
"""Draw an ``image`` on the Canvas at the coordinates (``x``, ``y``) and scale it to (``width``, ``height``)."""
382382
if (not isinstance(image, (Canvas, Image))):
383383
raise TypeError('The image argument should be an Image widget or a Canvas widget')
@@ -389,15 +389,15 @@ def draw_image(self, image, x, y, width=None, height=None):
389389

390390
self._send_canvas_command('drawImage', (serialized_image, x, y, width, height))
391391

392-
def put_image_data(self, image_data, dx=0, dy=0):
392+
def put_image_data(self, image_data, x=0, y=0):
393393
"""Draw an image on the Canvas.
394394
395-
``image_data`` should be a NumPy array containing the image to draw and ``dx`` and ``dy`` the pixel position where to
395+
``image_data`` should be a NumPy array containing the image to draw and ``x`` and ``y`` the pixel position where to
396396
draw. Unlike the CanvasRenderingContext2D.putImageData method, this method **is** affected by the canvas transformation
397397
matrix, and supports transparency.
398398
"""
399399
image_metadata, image_buffer = binary_image(image_data)
400-
self._send_canvas_command('putImageData', (image_metadata, dx, dy), (image_buffer, ))
400+
self._send_canvas_command('putImageData', (image_metadata, x, y), (image_buffer, ))
401401

402402
def create_image_data(self, width, height):
403403
"""Create a NumPy array of shape (width, height, 4) representing a table of pixel colors."""

0 commit comments

Comments
 (0)