Skip to content

Commit a623320

Browse files
committed
Add another example + stroke and fill color
1 parent 707237b commit a623320

File tree

3 files changed

+174
-21
lines changed

3 files changed

+174
-21
lines changed

examples/introduction.ipynb

Lines changed: 156 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
"outputs": [],
2626
"source": [
2727
"c = ipycanvas.Canvas()\n",
28-
"c.layout.height = '200px'"
28+
"c.layout.height = '200px'\n",
29+
"\n",
30+
"c"
2931
]
3032
},
3133
{
@@ -34,6 +36,23 @@
3436
"metadata": {},
3537
"outputs": [],
3638
"source": [
39+
"# Draw simple triangle shape\n",
40+
"c.begin_path()\n",
41+
"c.move_to(75, 50)\n",
42+
"c.line_to(100, 75)\n",
43+
"c.line_to(100, 25)\n",
44+
"c.fill()"
45+
]
46+
},
47+
{
48+
"cell_type": "code",
49+
"execution_count": null,
50+
"metadata": {},
51+
"outputs": [],
52+
"source": [
53+
"c = ipycanvas.Canvas(stroke_style='red')\n",
54+
"c.layout.height = '200px'\n",
55+
"\n",
3756
"c"
3857
]
3958
},
@@ -44,15 +63,16 @@
4463
"outputs": [],
4564
"source": [
4665
"# Draw smiley face\n",
47-
"c.begin_path();\n",
48-
"c.arc(75, 75, 50, 0, pi * 2, True); # Outer circle\n",
49-
"c.move_to(110, 75);\n",
50-
"c.arc(75, 75, 35, 0, pi, False); # Mouth (clockwise)\n",
51-
"c.move_to(65, 65);\n",
52-
"c.arc(60, 65, 5, 0, pi * 2, True); # Left eye\n",
53-
"c.move_to(95, 65);\n",
54-
"c.arc(90, 65, 5, 0, pi * 2, True); # Right eye\n",
55-
"c.stroke();"
66+
"# c.stroke_style='red'\n",
67+
"c.begin_path()\n",
68+
"c.arc(75, 75, 50, 0, pi * 2, True) # Outer circle\n",
69+
"c.move_to(110, 75)\n",
70+
"c.arc(75, 75, 35, 0, pi, False) # Mouth (clockwise)\n",
71+
"c.move_to(65, 65)\n",
72+
"c.arc(60, 65, 5, 0, pi * 2, True) # Left eye\n",
73+
"c.move_to(95, 65)\n",
74+
"c.arc(90, 65, 5, 0, pi * 2, True) # Right eye\n",
75+
"c.stroke()"
5676
]
5777
},
5878
{
@@ -61,13 +81,133 @@
6181
"metadata": {},
6282
"outputs": [],
6383
"source": [
64-
"# Draw simple triangle shape\n",
65-
"c.begin_path();\n",
66-
"c.move_to(75, 50);\n",
67-
"c.line_to(100, 75);\n",
68-
"c.line_to(100, 25);\n",
69-
"c.fill();"
84+
"c = ipycanvas.Canvas()\n",
85+
"c.layout.height = '200px'\n",
86+
"\n",
87+
"c"
7088
]
89+
},
90+
{
91+
"cell_type": "code",
92+
"execution_count": null,
93+
"metadata": {},
94+
"outputs": [],
95+
"source": [
96+
"# Draw bubble\n",
97+
"c.begin_path()\n",
98+
"c.move_to(75, 25)\n",
99+
"c.quadratic_curve_to(25, 25, 25, 62.5)\n",
100+
"c.quadratic_curve_to(25, 100, 50, 100)\n",
101+
"c.quadratic_curve_to(50, 120, 30, 125)\n",
102+
"c.quadratic_curve_to(60, 120, 65, 100)\n",
103+
"c.quadratic_curve_to(125, 100, 125, 62.5)\n",
104+
"c.quadratic_curve_to(125, 25, 75, 25)\n",
105+
"c.stroke()"
106+
]
107+
},
108+
{
109+
"cell_type": "code",
110+
"execution_count": null,
111+
"metadata": {},
112+
"outputs": [],
113+
"source": [
114+
"c = ipycanvas.Canvas()\n",
115+
"c.layout.height = '200px'\n",
116+
"\n",
117+
"c"
118+
]
119+
},
120+
{
121+
"cell_type": "code",
122+
"execution_count": null,
123+
"metadata": {},
124+
"outputs": [],
125+
"source": [
126+
"def rounded_rect(c, x, y, width, height, radius):\n",
127+
" c.begin_path()\n",
128+
" c.move_to(x, y + radius)\n",
129+
" c.line_to(x, y + height - radius)\n",
130+
" c.arc_to(x, y + height, x + radius, y + height, radius)\n",
131+
" c.line_to(x + width - radius, y + height)\n",
132+
" c.arc_to(x + width, y + height, x + width, y + height - radius, radius)\n",
133+
" c.line_to(x + width, y + radius)\n",
134+
" c.arc_to(x + width, y, x + width - radius, y, radius)\n",
135+
" c.line_to(x + radius, y)\n",
136+
" c.arc_to(x, y, x, y + radius, radius)\n",
137+
" c.stroke()"
138+
]
139+
},
140+
{
141+
"cell_type": "code",
142+
"execution_count": null,
143+
"metadata": {},
144+
"outputs": [],
145+
"source": [
146+
"rounded_rect(c, 12, 12, 150, 150, 15)\n",
147+
"rounded_rect(c, 19, 19, 150, 150, 9)\n",
148+
"rounded_rect(c, 53, 53, 49, 33, 10)\n",
149+
"rounded_rect(c, 53, 119, 49, 16, 6)\n",
150+
"rounded_rect(c, 135, 53, 49, 33, 10)\n",
151+
"rounded_rect(c, 135, 119, 25, 49, 10)\n",
152+
"\n",
153+
"c.begin_path()\n",
154+
"c.arc(37, 37, 13, pi / 7, -pi / 7, False)\n",
155+
"c.line_to(31, 37)\n",
156+
"c.fill()\n",
157+
"\n",
158+
"for i in range(8):\n",
159+
" c.fill_rect(51 + i * 16, 35, 4, 4)\n",
160+
"\n",
161+
"for i in range(6):\n",
162+
" c.fill_rect(115, 51 + i * 16, 4, 4)\n",
163+
"\n",
164+
"for i in range(8):\n",
165+
" c.fill_rect(51 + i * 16, 99, 4, 4)\n",
166+
"\n",
167+
"c.begin_path()\n",
168+
"c.move_to(83, 116)\n",
169+
"c.line_to(83, 102)\n",
170+
"c.bezier_curve_to(83, 94, 89, 88, 97, 88)\n",
171+
"c.bezier_curve_to(105, 88, 111, 94, 111, 102)\n",
172+
"c.line_to(111, 116)\n",
173+
"c.line_to(106.333, 111.333)\n",
174+
"c.line_to(101.666, 116)\n",
175+
"c.line_to(97, 111.333)\n",
176+
"c.line_to(92.333, 116)\n",
177+
"c.line_to(87.666, 111.333)\n",
178+
"c.line_to(83, 116)\n",
179+
"c.fill()\n",
180+
"\n",
181+
"c.fill_style = 'white'\n",
182+
"c.begin_path()\n",
183+
"c.move_to(91, 96)\n",
184+
"c.bezier_curve_to(88, 96, 87, 99, 87, 101)\n",
185+
"c.bezier_curve_to(87, 103, 88, 106, 91, 106)\n",
186+
"c.bezier_curve_to(94, 106, 95, 103, 95, 101)\n",
187+
"c.bezier_curve_to(95, 99, 94, 96, 91, 96)\n",
188+
"c.move_to(103, 96)\n",
189+
"c.bezier_curve_to(100, 96, 99, 99, 99, 101)\n",
190+
"c.bezier_curve_to(99, 103, 100, 106, 103, 106)\n",
191+
"c.bezier_curve_to(106, 106, 107, 103, 107, 101)\n",
192+
"c.bezier_curve_to(107, 99, 106, 96, 103, 96)\n",
193+
"c.fill()\n",
194+
"\n",
195+
"c.fill_style = 'black'\n",
196+
"c.begin_path()\n",
197+
"c.arc(101, 102, 2, 0, pi * 2, True)\n",
198+
"c.fill()\n",
199+
"\n",
200+
"c.begin_path()\n",
201+
"c.arc(89, 102, 2, 0, pi * 2, True)\n",
202+
"c.fill()"
203+
]
204+
},
205+
{
206+
"cell_type": "code",
207+
"execution_count": null,
208+
"metadata": {},
209+
"outputs": [],
210+
"source": []
71211
}
72212
],
73213
"metadata": {

ipycanvas/canvas.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
# Copyright (c) Martin Renou.
55
# Distributed under the terms of the Modified BSD License.
66

7-
from ipywidgets import DOMWidget
7+
from ipywidgets import DOMWidget, Color
8+
89
from traitlets import Unicode
10+
911
from ._frontend import module_name, module_version
1012

1113

@@ -17,6 +19,9 @@ class Canvas(DOMWidget):
1719
_view_module = Unicode(module_name).tag(sync=True)
1820
_view_module_version = Unicode(module_version).tag(sync=True)
1921

22+
fill_style = Color('black').tag(sync=True)
23+
stroke_style = Color('black').tag(sync=True)
24+
2025
# Rectangles methods
2126
def fill_rect(self, x, y, width, height):
2227
"""Draw a filled rectangle."""
@@ -30,6 +35,10 @@ def clear_rect(self, x, y, width, height):
3035
"""Clear the specified rectangular area, making it fully transparent."""
3136
self._send_canvas_msg('clearRect', x, y, width, height)
3237

38+
def rect(self, x, y, width, height):
39+
"""Draw a rectangle whose top-left corner is specified by (x, y) with the specified width and height."""
40+
self._send_canvas_msg('rect', x, y, width, height)
41+
3342
# Paths methods
3443
def begin_path(self):
3544
self._send_canvas_msg('beginPath')
@@ -61,8 +70,5 @@ def quadratic_curve_to(self, cp1x, cp1y, x, y):
6170
def bezier_curve_to(self, cp1x, cp1y, cp2x, cp2y, x, y):
6271
self._send_canvas_msg('bezierCurveTo', cp1x, cp1y, cp2x, cp2y, x, y)
6372

64-
def rect(self, x, y, width, height):
65-
self._send_canvas_msg('rect', x, y, width, height)
66-
6773
def _send_canvas_msg(self, msg_name, *args):
6874
self.send({'msg': msg_name, 'args': args})

src/widget.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ class CanvasModel extends DOMWidgetModel {
2121
_model_module_version: CanvasModel.model_module_version,
2222
_view_name: CanvasModel.view_name,
2323
_view_module: CanvasModel.view_module,
24-
_view_module_version: CanvasModel.view_module_version
24+
_view_module_version: CanvasModel.view_module_version,
25+
fill_style: 'black',
26+
stroke_style: 'black'
2527
};
2628
}
2729

@@ -59,6 +61,9 @@ class CanvasView extends DOMWidgetView {
5961

6062
model_events() {
6163
this.model.on('msg:custom', (event) => {
64+
this.ctx.fillStyle = this.model.get('fill_style');
65+
this.ctx.strokeStyle = this.model.get('stroke_style');
66+
6267
this.ctx[event.msg](...event.args);
6368
});
6469
}
@@ -74,6 +79,8 @@ class CanvasView extends DOMWidgetView {
7479
}
7580

7681
resize_canvas() {
82+
// TODO replay all drawings after resize?
83+
7784
const rect = this.el.getBoundingClientRect();
7885
this.canvas.setAttribute('width', rect.width);
7986
this.canvas.setAttribute('height', rect.height);

0 commit comments

Comments
 (0)