Use text but not marker in matplotlib legend

后端 未结 2 1064
暗喜
暗喜 2021-01-19 23:58

I am using FontAwesome in my chart, and each data point is a symbol in FontAwesome font, displaying like an icon. Therefore, in the legend, I would like to use text (symbols

相关标签:
2条回答
  • 2021-01-20 00:32

    For a solution using TextArea see this answer. You would then need to recreate the fontproperties for the text inside the TextArea.

    Since here you want to show exactly the symbol you have as text also in the legend, a simpler way to create a legend handler for some text object would be the following, which maps the text to a TextHandler. The TextHandler subclasses matplotlib.legend_handler.HandlerBase and its create_artists produces a copy of the text to show in the legend. Some of the text properties then need to be adjusted for the legend.

    import matplotlib.pyplot as plt
    from matplotlib.legend_handler import HandlerBase
    import copy
    
    ax = plt.gca()
    ax.axis([-1, 3,-1, 2])
    
    tx1 = ax.text(x=0, y=0, s=ur'$\u2660$', color='r',size=30, ha="right")
    tx2 = ax.text(x=2, y=0, s=ur'$\u2665$', color='g',size=30)
    
    
    class TextHandler(HandlerBase):
        def create_artists(self, legend, orig_handle,xdescent, ydescent,
                            width, height, fontsize,trans):
            h = copy.copy(orig_handle)
            h.set_position((width/2.,height/2.))
            h.set_transform(trans)
            h.set_ha("center");h.set_va("center")
            fp = orig_handle.get_font_properties().copy()
            fp.set_size(fontsize)
            # uncomment the following line, 
            # if legend symbol should have the same size as in the plot
            h.set_font_properties(fp)
            return [h]
    
    labels = ["label 1", "label 2"]
    handles = [tx1,tx2]
    handlermap = {type(tx1) : TextHandler()}
    ax.legend(handles, labels, handler_map=handlermap,) 
    
    plt.show()
    

    Also see this more generic answer

    0 讨论(0)
  • 2021-01-20 00:35

    Thanks for ImportanceOfBeingErnest's answer, I update his solution a little bit to generate Text in the legend handler:

    import matplotlib.pyplot as plt
    from matplotlib.legend_handler import HandlerBase
    import matplotlib.font_manager as fm
    from matplotlib.text import Text
    
    class TextLegend(object):
        def __init__(self, icon, color, **kwargs):
            self.icon = icon
            self.color = color
            self.kwargs = kwargs
    
    class TextLegendHandler(HandlerBase):
        def create_artists(self, legend, orig_handle, xdescent, ydescent,
                           width, height, fontsize, trans):
            x = xdescent + width / 2.0
            y = ydescent + height / 2.0
            kwargs = {
                'horizontalalignment': 'center',
                'verticalalignment': 'center',
                'color': orig_handle.color,
                'fontproperties': fm.FontProperties(fname='FontAwesome.otf', size=fontsize)
            }
            kwargs.update(orig_handle.kwargs)
            annotation = Text(x, y, orig_handle.icon, **kwargs)
            return [annotation]
    
    ax = plt.gca()
    ax.axis([0, 3, 0, 3])
    prop = fm.FontProperties(fname='FontAwesome.otf', size=18)
    ax.text(x=0, y=0, s='\uf1c7', color='r', fontproperties=prop)
    ax.text(x=2, y=0, s='\uf050', color='g', fontproperties=prop)
    
    plt.legend(
        handles=[TextLegend(color='r', icon='\uf1c7'), TextLegend(color='g', icon='\uf050')], 
        labels=['cat1', 'cat2'], 
        handler_map={TextLegend: TextLegendHandler()}
    )
    plt.show()
    

    0 讨论(0)
提交回复
热议问题