@@ -56,6 +56,21 @@ def _convert_collection_dash(linestyle):
5656 return "," .join ("{0:g}px" .format (d ) for d in dashes )
5757
5858
59+ def _has_blended_transform (transform ):
60+ """Check whether a matplotlib transform contains a blended transform."""
61+ if isinstance (
62+ transform , (transforms .BlendedGenericTransform , transforms .BlendedAffine2D )
63+ ):
64+ return True
65+ if hasattr (transform , "_a" ) and hasattr (transform , "_b" ):
66+ return _has_blended_transform (transform ._a ) or _has_blended_transform (
67+ transform ._b
68+ )
69+ if hasattr (transform , "_transform" ):
70+ return _has_blended_transform (transform ._transform )
71+ return False
72+
73+
5974class PlotlyRenderer (Renderer ):
6075 """A renderer class inheriting from base for rendering mpl plots in plotly.
6176
@@ -683,6 +698,39 @@ def _draw_axes_line(self, props):
683698 self .msg += " Heck yeah, I drew that reference line\n "
684699 return True
685700
701+ def _draw_axes_span (self , props ):
702+ """Draw a reference span (axhspan/axvspan) as a layout shape spanning
703+ the region in data coordinates."""
704+ ax = self .current_mpl_ax
705+ px_points = props ["data" ]
706+ data_points = [ax .transData .inverted ().transform (pt ) for pt in px_points ]
707+ xs = [pt [0 ] for pt in data_points ]
708+ ys = [pt [1 ] for pt in data_points ]
709+ x0 , x1 = float (min (xs )), float (max (xs ))
710+ y0 , y1 = float (min (ys )), float (max (ys ))
711+ style = props ["style" ]
712+ fillcolor = _export_color (style ["facecolor" ])
713+ edgecolor = _export_color (style ["edgecolor" ])
714+ linewidth = style ["edgewidth" ] if style ["edgecolor" ] != "none" else 0
715+ shape = go .layout .Shape (
716+ type = "rect" ,
717+ x0 = x0 ,
718+ y0 = y0 ,
719+ x1 = x1 ,
720+ y1 = y1 ,
721+ xref = "x{0}" .format (self .axis_ct ),
722+ yref = "y{0}" .format (self .axis_ct ),
723+ fillcolor = fillcolor ,
724+ line = go .layout .shape .Line (
725+ color = edgecolor ,
726+ width = linewidth ,
727+ dash = mpltools .convert_dash (style ["dasharray" ]),
728+ ),
729+ layer = "below" if style .get ("zorder" , 1 ) < 2 else "above" ,
730+ )
731+ self .plotly_fig ["layout" ]["shapes" ] += (shape ,)
732+ self .msg += " Heck yeah, I drew that reference span\n "
733+
686734 def draw_image (self , ** props ):
687735 """Draw image.
688736
@@ -908,6 +956,16 @@ def draw_path(self, **props):
908956 elif isinstance (props ["mplobj" ], mpatches .StepPatch ):
909957 self .msg += " Drawing a step path\n "
910958 self ._draw_step_path (props )
959+ elif (
960+ isinstance (props ["mplobj" ], (mpatches .Rectangle , mpatches .Polygon ))
961+ and props ["coordinates" ] == "display"
962+ and _has_blended_transform (props ["mplobj" ].get_transform ())
963+ ):
964+ if self ._processing_legend :
965+ self .msg += " Using native legend\n "
966+ else :
967+ self .msg += " Drawing an axes span\n "
968+ self ._draw_axes_span (props )
911969 else :
912970 self .msg += " This path isn't a bar, not drawing\n "
913971 warnings .warn (
0 commit comments