仕事柄長い時系列のデータを複数要素表示するグラフをよく描くのですが,少し気になる挙動がありました。
凡例の中の線がやや長過ぎる感じなのです。
次のようなコードで横長のグラフを描画してみます。
using Plots plt = plot(sin; xlims=(0, 100pi), size=(1600, 200), legendfontfamily="ipag", label="線が長過ぎる") savefig(plt, "plots-legend-line-too-long.png")
結果は次の通りです。やや線が長過ぎるような気がします。

で,GRバックエンド実装を見ると,この線の長さは
グラフ(subplot)の横幅を基準として3/45の比で設定されているようでした。
なるほど。グラフを横長にすると間延びして見えるはずです。
で,この部分を変更できるように魔改造してみます。
次のコードを実装します。
これは,gr_legend_base_factor_per_ratioという参照型の変数を作って,
グラフの横幅とlegendの基準長さとの比を可変にできるようにします。
using Plots @eval Plots begin """ gr_legend_base_factor_per_ratio legend描画時の横方向の基準(グラフの横幅/45)の比 デフォルトでは45となっている。 参照型なので, `gr_legend_base_factor_per_ratio[] = 100` のような形で変更すること """ const gr_legend_base_factor_per_ratio = Ref(45.0) function gr_get_legend_geometry(vp, sp) vertical = (legend_column = sp[:legend_column]) == 1 textw = texth = 0.0 has_title = false nseries = 0 if sp[:legend_position] !== :none GR.savestate() GR.selntran(0) GR.setcharup(0, 1) GR.setscale(0) ttl = sp[:legend_title] if (has_title = ttl !== nothing) gr_set_font(legendtitlefont(sp), sp) (l, r), (b, t) = extrema.(gr_inqtext(0, 0, string(ttl))) texth = t - b textw = r - l end gr_set_font(legendfont(sp), sp) for series in series_list(sp) should_add_to_legend(series) || continue (l, r), (b, t) = extrema.(gr_inqtext(0, 0, string(series[:label]))) texth = max(texth, t - b) textw = max(textw, r - l) # holds text width right now nseries += 1 end GR.setscale(GR.OPTION_X_LOG) GR.selntran(1) GR.restorestate() end # deal with layout column_layout = if legend_column == -1 (1, has_title + nseries) elseif legend_column > nseries && nseries != 0 # catch plot_title here @warn "n° of legend_column=$legend_column is larger than n° of series=$nseries" (1 + has_title, nseries) elseif legend_column == 0 @warn "n° of legend_column=$legend_column. Assuming vertical layout." vertical = true (has_title + nseries, 1) else (ceil(Int64, nseries / legend_column) + has_title, legend_column) end #println(column_layout) base_factor = width(vp) / gr_legend_base_factor_per_ratio[] # determines legend box base width (arbitrarily based on `width`) # legend box conventions ref(1) # ______________________________ # |<pad><span><space><text> <pad>| # | ---o-- ⋅ y1 | # |__________________↑___________| # (xpos,ypos) pad = 1base_factor # legend padding span = 3base_factor # horizontal span of the legend line: line x marker x line = 3base_factor space = 0.5base_factor # white space between text and legend / markers # increment between each legend entry ekw = sp[:extra_kwargs] dy = texth * get(ekw, :legend_hfactor, 1) span_hspace = span + pad # part of the horizontal increment dx = (textw + (vertical ? 0 : span_hspace)) * get(ekw, :legend_wfactor, 1) # This is to prevent that linestyle is obscured by large markers. # We are trying to get markers to not be larger than half the line length. # 1 / leg.dy translates base_factor to line length units (important in the context of size kwarg) # gr_legend_marker_to_line_factor is an empirical constant to translate between line length unit and marker size unit base_markersize = gr_legend_marker_to_line_factor[] * span / dy # NOTE: arbitrarily based on horizontal measures ! entries = has_title + nseries # number of legend entries # NOTE: subtract `span_hspace`, since it joins labels in horizontal mode w = dx * column_layout[2] - space - !vertical * span_hspace h = dy * column_layout[1] ( yoffset = height(vp) / 30, xoffset = width(vp) / 30, base_markersize, base_factor, has_title, vertical, entries, column_layout, space, texth, textw, span, pad, dy, dx, w, h, ) end end
上のコードを実行してから,次のように実行します。
# 凡例の基準長さをグラフ横幅の1/150にする Plots.gr_legend_base_factor_per_ratio[] = 150.0 plt = plot(sin; xlims=(0, 100pi), size=(1600, 200), legendfontfamily="ipag", label="線を調整") savefig(plt, "plots-legend-line-short.png")
結果は次の通りです。 凡例の線が短くなっていることが分かると思います。

このように内部の実装を覗いて自分だけの魔改造をするのも楽しいものです。
最近はプルリクで提案するのが普通なんでしょうが,この辺は好みなので 採用されないことも多いので,本体のライブラリを変更せずに 改造できるのは個人的には非常に重宝しています。
注意点
対応しているのはPlots.jlのバージョン1.xです。
いつかリリースされるバージョン2からはPlots.jlモジュールの構造が変わるので上記のコードでは動かないので注意して下さい。