1616
1717
1818def to_camel_case (snake_str ):
19- """Turn a snake_case string into a camelCase one."""
2019 components = snake_str .split ('_' )
2120 return components [0 ] + '' .join (x .title () for x in components [1 :])
2221
2322
2423class Canvas (DOMWidget ):
24+ """Create a Canvas widget.
25+
26+ Args:
27+ size (tuple): The size (in pixels) of the canvas
28+ """
29+
2530 _model_name = Unicode ('CanvasModel' ).tag (sync = True )
2631 _model_module = Unicode (module_name ).tag (sync = True )
2732 _model_module_version = Unicode (module_version ).tag (sync = True )
@@ -31,15 +36,33 @@ class Canvas(DOMWidget):
3136
3237 size = Tuple ((700 , 500 ), help = 'Size of the Canvas, this is not equal to the size of the view' ).tag (sync = True )
3338
39+ #: (valid HTML color) The color for filling rectangles and paths. Default to ``'black'``.
3440 fill_style = Color ('black' )
41+
42+ #: (valid HTML color) The color for rectangles and paths stroke. Default to ``'black'``.
3543 stroke_style = Color ('black' )
44+
45+ #: (float) Transparency level. Default to ``1.0``.
3646 global_alpha = Float (1.0 )
3747
48+ #: (str) Font for the text rendering. Default to ``'12px serif'``.
3849 font = Unicode ('12px serif' )
39- text_align = Unicode ('start' )
40- text_baseline = Unicode ('alphabetic' )
41- direction = Unicode ('inherit' )
4250
51+ #: (str) Text alignment, possible values are ``'start'``, ``'end'``, ``'left'``, ``'right'``, and ``'center'``.
52+ #: Default to ``'start'``.
53+ text_align = Enum (['start' , 'end' , 'left' , 'right' , 'center' ], default_value = 'start' )
54+
55+ #: (str) Text baseline, possible values are ``'top'``, ``'hanging'``, ``'middle'``, ``'alphabetic'``, ``'ideographic'``
56+ #: and ``'bottom'``.
57+ #: Default to ``'alphabetic'``.
58+ text_baseline = Enum (['top' , 'hanging' , 'middle' , 'alphabetic' , 'ideographic' , 'bottom' ], default_value = 'alphabetic' )
59+
60+ #: (str) Text direction, possible values are ``'ltr'``, ``'rtl'``, and ``'inherit'``.
61+ #: Default to ``'inherit'``.
62+ direction = Enum (['ltr' , 'rtl' , 'inherit' ], default_value = 'inherit' )
63+
64+ #: (str) Global composite operation, possible values are listed below:
65+ #: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Compositing#globalCompositeOperation
4366 global_composite_operation = Enum (
4467 ['source-over' , 'source-in' , 'source-out' , 'source-atop' ,
4568 'destination-over' , 'destination-in' , 'destination-out' ,
@@ -62,21 +85,17 @@ def __init__(self, *args, **kwargs):
6285
6386 # Rectangles methods
6487 def fill_rect (self , x , y , width , height ):
65- """Draw a filled rectangle."""
88+ """Draw a filled rectangle of size ``(width, height)`` at the ``(x, y)`` position ."""
6689 self ._send_canvas_command ('fillRect' , (x , y , width , height ))
6790
6891 def stroke_rect (self , x , y , width , height ):
69- """Draw a rectangular outline."""
92+ """Draw a rectangular outline of size ``(width, height)`` at the ``(x, y)`` position ."""
7093 self ._send_canvas_command ('strokeRect' , (x , y , width , height ))
7194
7295 def clear_rect (self , x , y , width , height ):
73- """Clear the specified rectangular area, making it fully transparent."""
96+ """Clear the specified rectangular area of size ``(width, height)`` at the ``(x, y)`` position , making it fully transparent."""
7497 self ._send_canvas_command ('clearRect' , (x , y , width , height ))
7598
76- def rect (self , x , y , width , height ):
77- """Draw a rectangle whose top-left corner is specified by (x, y) with the specified width and height."""
78- self ._send_canvas_command ('rect' , (x , y , width , height ))
79-
8099 # Paths methods
81100 def begin_path (self ):
82101 """Call this method when you want to create a new path."""
@@ -91,35 +110,42 @@ def close_path(self):
91110 self ._send_canvas_command ('closePath' )
92111
93112 def stroke (self ):
94- """Stroke (outlines) the current path with the current stroke style ."""
113+ """Stroke (outlines) the current path with the current ``stroke_style`` ."""
95114 self ._send_canvas_command ('stroke' )
96115
97116 def fill (self ):
98- """Fill the current or given path with the current fillStyle ."""
117+ """Fill the current or given path with the current ``fill_style`` ."""
99118 self ._send_canvas_command ('fill' )
100119
101120 def move_to (self , x , y ):
102- """Move the "pen" to the given (x, y) coordinates."""
121+ """Move the "pen" to the given `` (x, y)`` coordinates."""
103122 self ._send_canvas_command ('moveTo' , (x , y ))
104123
105124 def line_to (self , x , y ):
106- """Add a straight line to the current path by connecting the path's last point to the specified (x, y) coordinates.
125+ """Add a straight line to the current path by connecting the path's last point to the specified `` (x, y)`` coordinates.
107126
108127 Like other methods that modify the current path, this method does not directly render anything. To
109128 draw the path onto the canvas, you can use the fill() or stroke() methods.
110129 """
111130 self ._send_canvas_command ('lineTo' , (x , y ))
112131
132+ def rect (self , x , y , width , height ):
133+ """Draw a rectangle of size ``(width, height)`` at the ``(x, y)`` position in the current path."""
134+ self ._send_canvas_command ('rect' , (x , y , width , height ))
135+
113136 def arc (self , x , y , radius , start_angle , end_angle , anticlockwise = False ):
114- """Create a circular arc centered at (x, y) with a radius of radius.
137+ """Create a circular arc centered at `` (x, y)`` with a radius of `` radius`` .
115138
116- The path starts at startAngle and ends at endAngle , and travels in the direction given by
117- anticlockwise (defaulting to clockwise).
139+ The path starts at ``start_angle`` and ends at ``end_angle`` , and travels in the direction given by
140+ `` anticlockwise`` (defaulting to clockwise: ``False`` ).
118141 """
119142 self ._send_canvas_command ('arc' , (x , y , radius , start_angle , end_angle , anticlockwise ))
120143
121144 def arc_to (self , x1 , y1 , x2 , y2 , radius ):
122- """Add a circular arc to the current path, using the given control points and radius."""
145+ """Add a circular arc to the current path.
146+
147+ Using the given control points ``(x1, y1)`` and ``(x2, y2)`` and the ``radius``.
148+ """
123149 self ._send_canvas_command ('arcTo' , (x1 , y1 , x2 , y2 , radius ))
124150
125151 def quadratic_curve_to (self , cp1x , cp1y , x , y ):
@@ -142,11 +168,11 @@ def bezier_curve_to(self, cp1x, cp1y, cp2x, cp2y, x, y):
142168
143169 # Text methods
144170 def fill_text (self , text , x , y , max_width = None ):
145- """Fill a given text at the given (x,y) position. Optionally with a maximum width to draw."""
171+ """Fill a given text at the given `` (x, y)`` position. Optionally with a maximum width to draw."""
146172 self ._send_canvas_command ('fillText' , (text , x , y , max_width ))
147173
148174 def stroke_text (self , text , x , y , max_width = None ):
149- """Stroke a given text at the given (x,y) position. Optionally with a maximum width to draw."""
175+ """Stroke a given text at the given `` (x, y)`` position. Optionally with a maximum width to draw."""
150176 self ._send_canvas_command ('strokeText' , (text , x , y , max_width ))
151177
152178 # Image methods
@@ -264,6 +290,13 @@ def _send_command(self, command, buffers=[]):
264290
265291
266292class MultiCanvas (DOMWidget ):
293+ """Create a MultiCanvas widget with n_canvases Canvas widgets.
294+
295+ Args:
296+ n_canvases (int): The number of canvases to create
297+ size (tuple): The size (in pixels) of the canvases
298+ """
299+
267300 _model_name = Unicode ('MultiCanvasModel' ).tag (sync = True )
268301 _model_module = Unicode (module_name ).tag (sync = True )
269302 _model_module_version = Unicode (module_version ).tag (sync = True )
@@ -276,7 +309,7 @@ class MultiCanvas(DOMWidget):
276309 _canvases = List (Instance (Canvas )).tag (sync = True , ** widget_serialization )
277310
278311 def __init__ (self , n_canvases = 3 , * args , ** kwargs ):
279- """Create a MultiCanvas widget with n_canvases Canvas widgets ."""
312+ """Constructor ."""
280313 size = kwargs .get ('size' , (700 , 500 ))
281314
282315 super (MultiCanvas , self ).__init__ (* args , _canvases = [Canvas (size = size ) for _ in range (n_canvases )], ** kwargs )
@@ -295,7 +328,13 @@ def _on_size_change(self, change):
295328
296329@contextmanager
297330def hold_canvas (canvas ):
298- """Hold any drawing on the canvas, and perform only one draw command at the end."""
331+ """Hold any drawing on the canvas, and perform all commands in a single shot at the end.
332+
333+ This is way more efficient than sending commands one by one.
334+
335+ Args:
336+ canvas (ipycanvas.canvas.Canvas): The canvas widget on which to hold the commands
337+ """
299338 canvas .caching = True
300339 yield
301340 canvas .flush ()
0 commit comments