@@ -92,8 +92,8 @@ def __init__(self, parent, handles, labels,
9292 handlelen = None , # the length of the legend lines
9393 handletextsep = None , # the space between the legend line and legend text
9494 axespad = None , # the border between the axes and legend edge
95-
96- shadow = None
95+ shadow = None ,
96+ scatteryoffsets = None ,
9797 ):
9898 """
9999 parent # the artist that contains the legend
@@ -105,6 +105,7 @@ def __init__(self, parent, handles, labels,
105105 pad = 0.2 # the fractional whitespace inside the legend border
106106 markerscale = 0.6 # the relative size of legend markers vs. original
107107 shadow # if True, draw a shadow behind legend
108+ scatteryoffsets # a list of yoffsets for scatter symbols in legend
108109
109110The following dimensions are in axes coords
110111 labelsep = 0.005 # the vertical space between the legend entries
@@ -117,8 +118,10 @@ def __init__(self, parent, handles, labels,
117118
118119 Artist .__init__ (self )
119120
120- proplist = [numpoints , pad , borderpad , markerscale , labelsep , handlelen , handletextsep , axespad , shadow ]
121- propnames = ['numpoints' , 'pad' , 'borderpad' , 'markerscale' , 'labelsep' , 'handlelen' , 'handletextsep' , 'axespad' , 'shadow' ]
121+ proplist = [numpoints , pad , borderpad , markerscale , labelsep ,
122+ handlelen , handletextsep , axespad , shadow , scatteryoffsets ]
123+ propnames = ['numpoints' , 'pad' , 'borderpad' , 'markerscale' , 'labelsep' ,
124+ 'handlelen' , 'handletextsep' , 'axespad' , 'shadow' , 'scatteryoffsets' ]
122125 for name , value in safezip (propnames ,proplist ):
123126 if value is None :
124127 value = rcParams ["legend." + name ]
@@ -134,6 +137,14 @@ def __init__(self, parent, handles, labels,
134137 self .prop = prop
135138 self .fontsize = self .prop .get_size_in_points ()
136139
140+ # introduce y-offset for handles of the scatter plot
141+ if scatteryoffsets is None :
142+ self ._scatteryoffsets = np .array ([4. / 8. , 5. / 8. , 3. / 8. ])
143+ else :
144+ self ._scatteryoffsets = np .asarray (scatteryoffsets )
145+ reps = int (self .numpoints / len (self ._scatteryoffsets )) + 1
146+ self ._scatteryoffsets = np .tile (self ._scatteryoffsets , reps )[:self .numpoints ]
147+
137148 if isinstance (parent ,Axes ):
138149 self .isaxes = True
139150 self .set_figure (parent .figure )
@@ -306,15 +317,26 @@ def _get_handles(self, handles, texts):
306317 ret .append (legline )
307318
308319 elif isinstance (handle , RegularPolyCollection ):
309- if self .numpoints == 1 :
310- xdata = np .array ([left ])
311- p = Rectangle (xy = (min (xdata ), y - 3 / 4 * HEIGHT ),
312- width = self .handlelen , height = HEIGHT / 2 ,
313- )
314- p .set_facecolor (handle ._facecolors [0 ])
315- if handle ._edgecolors != 'none' and len (handle ._edgecolors ):
316- p .set_edgecolor (handle ._edgecolors [0 ])
317- self ._set_artist_props (p )
320+ # the ydata values set here have no effects as it will
321+ # be updated in the _update_positions() method.
322+ ydata = (y - HEIGHT / 2 )* np .ones (np .asarray (xdata_marker ).shape , float )
323+
324+ size_max , size_min = max (handle .get_sizes ()),\
325+ min (handle .get_sizes ())
326+ # we may need to scale these sizes by "markerscale"
327+ # attribute. But other handle types does not seem
328+ # to care about this attribute and it is currently ignored.
329+ sizes = [.5 * (size_max + size_min ), size_max ,
330+ size_min ]
331+
332+ p = type (handle )(handle .get_numsides (),
333+ rotation = handle .get_rotation (),
334+ sizes = sizes ,
335+ offsets = zip (xdata_marker ,ydata ),
336+ transOffset = self .get_transform ())
337+
338+ p .update_from (handle )
339+ p .set_figure (self .figure )
318340 p .set_clip_box (None )
319341 p .set_clip_path (None )
320342 ret .append (p )
@@ -532,6 +554,10 @@ def get_tbounds(text): #get text bounds in axes coords
532554 elif isinstance (handle , Rectangle ):
533555 handle .set_y (y + 1 / 4 * h )
534556 handle .set_height (h / 2 )
557+ elif isinstance (handle ,RegularPolyCollection ):
558+ offsets = handle .get_offsets ()
559+ offsets [:,1 ] = y + h * self ._scatteryoffsets
560+ handle .set_offsets (offsets )
535561
536562 # Set the data for the legend patch
537563 bbox = self ._get_handle_text_bbox (renderer )
0 commit comments