Skip to content

Commit ec6f9f9

Browse files
authored
Merge pull request #21 from martinRenou/lines_parameters
Lines parameters
2 parents 57ff737 + 0d46512 commit ec6f9f9

File tree

2 files changed

+242
-1
lines changed

2 files changed

+242
-1
lines changed

examples/lines.ipynb

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"metadata": {},
7+
"outputs": [],
8+
"source": [
9+
"from ipycanvas import Canvas"
10+
]
11+
},
12+
{
13+
"cell_type": "markdown",
14+
"metadata": {},
15+
"source": [
16+
"# Line width:\n",
17+
"### Sets the width of lines drawn in the future."
18+
]
19+
},
20+
{
21+
"cell_type": "code",
22+
"execution_count": null,
23+
"metadata": {},
24+
"outputs": [],
25+
"source": [
26+
"size = (400, 280)\n",
27+
"\n",
28+
"canvas = Canvas(size=size)\n",
29+
"canvas.scale(2)\n",
30+
"\n",
31+
"for i in range(10):\n",
32+
" width = 1 + i\n",
33+
" x = 5 + i * 20\n",
34+
" canvas.line_width = width\n",
35+
"\n",
36+
" canvas.fill_text(str(width), x - 5, 15)\n",
37+
"\n",
38+
" canvas.begin_path()\n",
39+
" canvas.move_to(x, 20)\n",
40+
" canvas.line_to(x, 140)\n",
41+
" canvas.stroke()\n",
42+
"canvas"
43+
]
44+
},
45+
{
46+
"cell_type": "markdown",
47+
"metadata": {},
48+
"source": [
49+
"# Line cap\n",
50+
"### Sets the appearance of the ends of lines."
51+
]
52+
},
53+
{
54+
"cell_type": "code",
55+
"execution_count": null,
56+
"metadata": {},
57+
"outputs": [],
58+
"source": [
59+
"size = (320, 360)\n",
60+
"\n",
61+
"canvas = Canvas(size=size)\n",
62+
"\n",
63+
"# Possible line_cap values\n",
64+
"line_caps = ['butt', 'round', 'square']\n",
65+
"\n",
66+
"canvas.scale(2)\n",
67+
"\n",
68+
"# Draw guides\n",
69+
"canvas.stroke_style = '#09f'\n",
70+
"canvas.begin_path()\n",
71+
"canvas.move_to(10, 30)\n",
72+
"canvas.line_to(140, 30)\n",
73+
"canvas.move_to(10, 140)\n",
74+
"canvas.line_to(140, 140)\n",
75+
"canvas.stroke()\n",
76+
"\n",
77+
"# Draw lines\n",
78+
"canvas.stroke_style = 'black'\n",
79+
"canvas.font = '15px serif'\n",
80+
"\n",
81+
"for i in range(len(line_caps)):\n",
82+
" line_cap = line_caps[i]\n",
83+
" x = 25 + i * 50\n",
84+
"\n",
85+
" canvas.fill_text(line_cap, x - 15, 15)\n",
86+
" canvas.line_width = 15\n",
87+
" canvas.line_cap = line_cap\n",
88+
" canvas.begin_path()\n",
89+
" canvas.move_to(x, 30)\n",
90+
" canvas.line_to(x, 140)\n",
91+
" canvas.stroke()\n",
92+
"\n",
93+
"canvas"
94+
]
95+
},
96+
{
97+
"cell_type": "markdown",
98+
"metadata": {},
99+
"source": [
100+
"# Line join\n",
101+
"### Sets the appearance of the \"corners\" where lines meet."
102+
]
103+
},
104+
{
105+
"cell_type": "code",
106+
"execution_count": null,
107+
"metadata": {},
108+
"outputs": [],
109+
"source": [
110+
"size = (320, 360)\n",
111+
"\n",
112+
"canvas = Canvas(size=size)\n",
113+
"\n",
114+
"# Possible line_join values\n",
115+
"line_joins = ['round', 'bevel', 'miter']\n",
116+
"\n",
117+
"min_y = 40\n",
118+
"max_y = 80\n",
119+
"spacing = 45\n",
120+
"\n",
121+
"canvas.line_width = 10\n",
122+
"canvas.scale(2)\n",
123+
"for i in range(len(line_joins)):\n",
124+
" line_join = line_joins[i]\n",
125+
" \n",
126+
" y1 = min_y + i * spacing\n",
127+
" y2 = max_y + i * spacing\n",
128+
"\n",
129+
" canvas.line_join = line_join\n",
130+
"\n",
131+
" canvas.fill_text(line_join, 60, y1 - 10)\n",
132+
"\n",
133+
" canvas.begin_path()\n",
134+
" canvas.move_to(-5, y1)\n",
135+
" canvas.line_to(35, y2)\n",
136+
" canvas.line_to(75, y1)\n",
137+
" canvas.line_to(115, y2)\n",
138+
" canvas.line_to(155, y1)\n",
139+
" canvas.stroke()\n",
140+
"\n",
141+
"canvas"
142+
]
143+
},
144+
{
145+
"cell_type": "markdown",
146+
"metadata": {},
147+
"source": [
148+
"# Line dash\n",
149+
"### Sets the current line dash pattern."
150+
]
151+
},
152+
{
153+
"cell_type": "code",
154+
"execution_count": null,
155+
"metadata": {},
156+
"outputs": [],
157+
"source": [
158+
"size = (400, 280)\n",
159+
"\n",
160+
"canvas = Canvas(size=size)\n",
161+
"canvas.scale(2)\n",
162+
"\n",
163+
"line_dashes = [\n",
164+
" [5, 10],\n",
165+
" [10, 5],\n",
166+
" [5, 10, 20],\n",
167+
" [10, 20],\n",
168+
" [20, 10],\n",
169+
" [20, 20]\n",
170+
"]\n",
171+
"\n",
172+
"canvas.line_width = 2\n",
173+
"\n",
174+
"for i in range(len(line_dashes)):\n",
175+
" x = 5 + i * 20\n",
176+
"\n",
177+
" canvas.set_line_dash(line_dashes[i])\n",
178+
" canvas.begin_path()\n",
179+
" canvas.move_to(x, 0)\n",
180+
" canvas.line_to(x, 140)\n",
181+
" canvas.stroke()\n",
182+
"canvas"
183+
]
184+
}
185+
],
186+
"metadata": {
187+
"kernelspec": {
188+
"display_name": "Python 3",
189+
"language": "python",
190+
"name": "python3"
191+
},
192+
"language_info": {
193+
"codemirror_mode": {
194+
"name": "ipython",
195+
"version": 3
196+
},
197+
"file_extension": ".py",
198+
"mimetype": "text/x-python",
199+
"name": "python",
200+
"nbconvert_exporter": "python",
201+
"pygments_lexer": "ipython3",
202+
"version": "3.7.3"
203+
}
204+
},
205+
"nbformat": 4,
206+
"nbformat_minor": 4
207+
}

ipycanvas/canvas.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,26 @@ class Canvas(DOMWidget):
7474
default_value='source-over'
7575
)
7676

77+
#: (float) Sets the width of lines drawn in the future, must be a positive number. Default to ``1.0``.
78+
line_width = Float(1.0)
79+
80+
#: (str) Sets the appearance of the ends of lines, possible values are ``'butt'``, ``'round'`` and ``'square'``.
81+
#: Default to ``'butt'``.
82+
line_cap = Enum(['butt', 'round', 'square'], default_value='butt')
83+
84+
#: (str) Sets the appearance of the "corners" where lines meet, possible values are ``'round'``, ``'bevel'`` and ``'miter'``.
85+
#: Default to ``'miter'``
86+
line_join = Enum(['round', 'bevel', 'miter'], default_value='miter')
87+
88+
#: (float) Establishes a limit on the miter when two lines join at a sharp angle, to let you control how thick
89+
#: the junction becomes. Default to ``10.``.
90+
miter_limit = Float(10.)
91+
92+
_line_dash = List()
93+
94+
#: (float) Specifies where to start a dash array on a line. Default is ``0.``.
95+
line_dash_offset = Float(0.)
96+
7797
def __init__(self, *args, **kwargs):
7898
"""Create a Canvas widget."""
7999
#: Whether commands should be cached or not
@@ -177,6 +197,19 @@ def stroke_text(self, text, x, y, max_width=None):
177197
"""Stroke a given text at the given ``(x, y)`` position. Optionally with a maximum width to draw."""
178198
self._send_canvas_command('strokeText', (text, x, y, max_width))
179199

200+
# Line methods
201+
def get_line_dash(self):
202+
"""Return the current line dash pattern array containing an even number of non-negative numbers."""
203+
return self._line_dash
204+
205+
def set_line_dash(self, segments):
206+
"""Set the current line dash pattern."""
207+
if len(segments) % 2:
208+
self._line_dash = segments + segments
209+
else:
210+
self._line_dash = segments
211+
self._send_canvas_command('setLineDash', (self._line_dash, ))
212+
180213
# Image methods
181214
def put_image_data(self, image_data, dx, dy):
182215
"""Draw an image on the Canvas.
@@ -268,7 +301,8 @@ def flush(self):
268301
self._buffers_cache = []
269302

270303
@observe('fill_style', 'stroke_style', 'global_alpha', 'font', 'text_align',
271-
'text_baseline', 'direction', 'global_composite_operation')
304+
'text_baseline', 'direction', 'global_composite_operation',
305+
'line_width', 'line_cap', 'line_join', 'miter_limit', 'line_dash_offset')
272306
def _on_set_attr(self, change):
273307
command = {
274308
'name': 'set',

0 commit comments

Comments
 (0)