Featured image of post Matplotlibでダークモード対応の図をいい感じに作る

Matplotlibでダークモード対応の図をいい感じに作る

表示要素に白色のボーダーを追加することで対応します

TL;DR

Matplotlibの表示要素に白色のボーダーを追加することで、同一の画像ファイルでライトモード(白背景)とダークモード(黒背景)の両方で見やすい表示となる作図方法をまとめました。 以下の例のように、図の背景を透明にしても線やテキストが黒背景に埋もれず、そこそこ見やすい形で両立できるようになります。

サイドバーからダークモードを切り替えて表示の違いを確認できます
サイドバーからダークモードを切り替えて表示の違いを確認できます

Path effects

表示要素(artists)にボーダーを追加するにはpath effects(matplotlib.patheffects)を使用します。 名前から分かるように、ボーダーを追加できるのはテキストやラインプロットなど線(パス)を持つ要素のみとなります。 今回の場合、withStroke()でボーダーの線の色と線幅を設定したpath effectオブジェクトを作成します。

import matplotlib as plt
from matplotlib.patheffects import withStroke


border = withStroke(linewidth=3, foreground="white")

Examples

ボーダーを追加するには、作成したpath effectオブジェクトを(1)rcParamsでグローバルに設定するか、(2)プロット関連の関数やメソッドが持つpath_effectsオプションで個別に設定するか、(3)表示要素が持つset_path_effects()メソッドで個別に設定します。 以下では(1)の例を紹介します。

with plt.rc_context({"path.effects": [border]}):
    plt.plot([1, 2, 1, 3], label="A")
    plt.plot([2, 1, 3, 2], label="B")
    plt.title("Darkmode-compatible figure")
    plt.legend()

plt.savefig("figure.png", transparent=True)

rc_context()を使うと、withブロックに書かれた要素のみにボーダーを適用することができます。 ここで、rcParamsの"path.effects"は複数の設定を受け取るため、[border]のように配列で渡すことに注意してください。

上の例では図(画像)の外周にもボーダーが追加されてしまうため若干見づらいかもしれません。 少し複雑になりますが、以下のように書くことで外周のボーダーを消すことができます。

fig = plt.figure()

with plt.rc_context({"path.effects": [border]}):
    ax = fig.add_subplot()
    ax.plot([1, 2, 1, 3], label="A")
    ax.plot([2, 1, 3, 2], label="B")
    ax.set_title("Darkmode-compatible figure")
    ax.legend()

fig.savefig("figure.png", transparent=True)

References

Licensed under CC BY 4.0
Last updated on 2021-08-15 20:00 +0900
Built with Hugo
Theme Stack designed by Jimmy