How to use Font Awesome symbol as marker in matplotlib

谁说胖子不能爱 提交于 2019-12-03 14:25:17

问题


Is it possible to use a font-awesome icon as a marker in a scatterplot with matplotlib? Or is it possible to use it as a font and put the icon as a 'text'?


This question has originally been asked here, but has been closed for an unknown reason. Since I consider it a valid and useful problem, which hasn't been addressed anywhere on Stackoverflow and sure deserves an answer, I will simply ask it again.

回答1:


FontAwesome is available from here. It provides its icons as vector graphics and as well as as otf-font.

Use FontAwesome otf font

Matplotlib cannot natively read vector graphics, but it can load otf-fonts. After downloading the FontAwesome package you can access the font via a matplotlib.font_manager.FontProperties object, e.g.

fp = FontProperties(fname=r"C:\Windows\Fonts\Font Awesome 5 Free-Solid-900.otf") 

Create texts

The FontProperties can be the input for matplotlib text objects

plt.text(.6, .4, "\uf16c", fontproperties=fp)

Unfortunately, using the FontAwesome ligatures is not possible. Hence the individual symbols need to be accessed via their UTF8 key. This is a little cumbersome, but the cheatsheet can come handy here. Storing those needed symbols in a dictionary with a meaningful name may make sense.

Example:

from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt

fp1 = FontProperties(fname=r"C:\Windows\Fonts\Font Awesome 5 Brands-Regular-400.otf")
fp2 = FontProperties(fname=r"C:\Windows\Fonts\Font Awesome 5 Free-Solid-900.otf")

symbols = dict(cloud = "\uf6c4", campground = "\uf6bb", hiking = "\uf6ec",
               mountain = "\uf6fc", tree = "\uf1bb", fish = "\uf578",
               stackoverflow = "\uf16c")

fig, (ax, ax2) = plt.subplots(ncols=2, figsize=(6.2, 2.2), sharey=True)
ax.text(.5, .5, symbols["stackoverflow"], fontproperties=fp1, size=100, 
         color="orange", ha="center", va="center")


ax2.stackplot([0,.3,.55,.6,.65,1],[.1,.2,.2,.2,.2,.15],[.3,.2,.2,.3,.2,.2],
              colors=["paleturquoise", "palegreen"])
ax2.axis([0,1,0,1])
ax2.text(.6, .4, symbols["mountain"], fontproperties=fp2, size=16, ha="center")
ax2.text(.09, .23, symbols["campground"], fontproperties=fp2, size=13)
ax2.text(.22, .27, symbols["hiking"], fontproperties=fp2, size=14)
ax2.text(.7, .24, symbols["tree"], fontproperties=fp2, size=14,color="forestgreen")
ax2.text(.8, .33, symbols["tree"], fontproperties=fp2, size=14,color="forestgreen")
ax2.text(.88, .28, symbols["tree"], fontproperties=fp2, size=14,color="forestgreen")
ax2.text(.35, .03, symbols["fish"], fontproperties=fp2, size=14,)
ax2.text(.2, .7, symbols["cloud"], fontproperties=fp2, size=28,)

plt.show()

Create markers

Creating a lot of texts like above is not really handy. To have the icons as markers would be nicer for certain applications. Matplotlib does have the ability to use utf symbols as markers, however, only through the mathtext functionality. Getting an otf font to be used as mathfont in matplotlib was unsuccessful in my trials.

An alternative is to create a matplotlib.path.Path from the symbol. This can be done via a matplotlib.textpath.TextToPath instance, which is unfortunately undocumented. The TextToPath has a method get_text_path taking a fontproperty and a string as input and returning the vertices and codes from which to create a Path. A Path can be used as a marker, e.g. for a scatter plot.

v, codes = TextToPath().get_text_path(fp, \uf6fc)
path = Path(v, codes, closed=False)
plt.scatter(..., marker=path)

Some example:

import numpy as np; np.random.seed(32)
from matplotlib.path import Path
from matplotlib.textpath import TextToPath
from matplotlib.font_manager import FontProperties
import matplotlib.pyplot as plt

fp = FontProperties(fname=r"C:\Windows\Fonts\Font Awesome 5 Free-Solid-900.otf")

symbols = dict(cloud = "\uf6c4", campground = "\uf6bb", hiking = "\uf6ec",
               mountain = "\uf6fc", tree = "\uf1bb", fish = "\uf578",
               stackoverflow = "\uf16c")

fig, ax = plt.subplots()

def get_marker(symbol):
    v, codes = TextToPath().get_text_path(fp, symbol)
    v = np.array(v)
    mean = np.mean([np.max(v,axis=0), np.min(v, axis=0)], axis=0)
    return Path(v-mean, codes, closed=False)

x = np.random.randn(4,10)
c = np.random.rand(10)
s = np.random.randint(120,500, size=10)
plt.scatter(*x[:2], s=s, c=c, marker=get_marker(symbols["cloud"]), 
            edgecolors="none", linewidth=2)
plt.scatter(*x[2:], s=s, c=c, marker=get_marker(symbols["fish"]), 
            edgecolors="none", linewidth=2)   

plt.show()



来源:https://stackoverflow.com/questions/52902086/how-to-use-font-awesome-symbol-as-marker-in-matplotlib

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!