share
MathematicaMake legend same height as plot
[+33] [7] Andrew Moylan
[2012-11-28 22:57:47]
[ plotting legending ]
[ https://mathematica.stackexchange.com/questions/15356/make-legend-same-height-as-plot ]

One common style for density plots is to have a vertical legend that is the same height as the plot itself. Some example density plots from Google Image search [1]:

Density plots from Google Image search

How can we make DensityPlots [2] with legends whose height matches the height of the plot? By default the heights are different:

DensityPlot[Sin[x] Sin[y], {x, -4, 4}, {y, -3, 3}, 
 PlotLegends -> Automatic]

Default DensityPlot with legend

(2) I guess you mean with the new built-in legending? If not, there's this - rm -rf
(2) You can resize them manually. They have handles you can drag. - Sjoerd C. de Vries
Maybe you can also use this - Jens
It is odd that it clips the top of the frame, just did it on my machine and I get the same image artifact ... ugh - Gabriel
[+17] [2012-11-29 10:30:14] Markus Roellig

Elaborating a little on Sjoerd's answer:

Specifying LegendMargins makes it even clearer that the fancy new legend might be not as useful as I first thought. We now have a working legend but lost basically all control over its apearance:

DensityPlot[Sin[x] Sin[y], {x, -4, 4}, {y, -3, 3}, 
 ImageSize -> {300, 300},
 ImagePadding -> {{30, 30}, {30, 30}}, Background -> LightGray, 
 PlotLegends -> 
 BarLegend["LakeColors", 
           LegendMargins -> {{10, 0}, {30, 20}}, 
           LegendFunction -> (Framed[#, FrameMargins -> 10] &)
           ]]

enter image description here

The upper edge of the BarLegend appears to allign roughly with the Plot canvas, but we now have the additional 30 points Margin at the top. Unfortunately if we change the Bottom Margin everything rescales:

DensityPlot[Sin[x] Sin[y], {x, -4, 4}, {y, -3, 3}, 
 ImageSize -> {300, 300},
 ImagePadding -> {{30, 30}, {30, 30}}, Background -> LightGray, 
 PlotLegends -> 
  BarLegend["LakeColors", 
            LegendMargins -> {{10, 0}, {10, 20}}, 
            LegendFunction -> (Framed[#, FrameMargins -> 10] &)
           ]]

enter image description here

Again the Legend claims additional space above and below the Plot. Imagine the nightmare in a GraphicsGrid with different kinds of Plots. To me, it appears as if the chance of ever aligning to Plots (and their Legends) next to each other are basically zero.

Looking at the InputForm of the above Plot gives a huge expression with Head Legended:

Legended[ .......,
{Placed[BarLegend["LakeColors", LegendFunction -> (Framed[#1, FrameMargins -> 10] & ), LegendLayout -> "Column", LegendMargins -> {{10, 0}, {10, 20}}, LegendMarkerSize -> 300, Charting`TickSide -> Right, ColorFunctionScaling -> True, LegendMargins -> {{10, 0}, {10, 20}},
LegendFunction -> (Framed[#1, FrameMargins -> 10] & )] , After, Identity]}]

We note two things: first there is the use of LegendMarkerSize that appears to take the vertical ImageSize. Fiddling with it can improve the result a little:

DensityPlot[Sin[x] Sin[y], {x, -4, 4}, {y, -3, 3}, 
 ImageSize -> {300, 300},
 ImagePadding -> {{30, 30}, {30, 30}}, Background -> LightGray, 
 PlotLegends -> 
  BarLegend["LakeColors", 
  LegendMargins -> {{10, 0}, {-10, -10}}, 
  LegendFunction -> (Framed[#, FrameMargins -> 10] &), 
  LegendMarkerSize -> 300]
 ]

gives:

enter image description here

The second thing is the usage of ChartingTickSide -> Right`, which controls where the Ticks are written.

I tried to find where the Charting*` stuff is defined, but could only get the following large list of expressions:

Names["Charting`*"]

{"Charting'angleCalc", "Charting'angleToValue", 
 "Charting'AngularScale", "Charting'apportion", 
 "Charting'AutomaticBar", "Charting'AutomaticBar3D", 
 "Charting'AutomaticBubble", "Charting'AutomaticBubble3D", 
 "Charting'AutomaticSector", "Charting'AutomaticSector3D", 
 "Charting'AutomaticTrap", "Charting'AxesLabelRotate", 
 "Charting'AxisAnnotation", "Charting'AxisAppearance", 
 "Charting'AxisFactor", "Charting'AxisLabel", "Charting'BackTesting", 
 "Charting'barPointtoValue", "Charting'barValHeight", 
 "Charting'barValueToPoint", "Charting'BoxElements", 
 "Charting'BulletCheck", "Charting'canonicalPlotLegends", 
 "Charting'canonicalWrapperLegends", "Charting'CanvasPadding", 
 "Charting'CategoricalAxis", "Charting'CategoryBounds", 
 "Charting'CategorySpacing", "Charting'ChartArgCheck", 
 "Charting'ChartHighlighting", "Charting'ChartLegendsParser", 
 "Charting'ChartParser", "Charting'ChartStyleBlock", 
 "Charting'ChartStyleInformation", "Charting'checkChartElement", 
 "Charting'checkColor", "Charting'checkGridLines", 
 "Charting'ClickEffect", "Charting'ClockCheck", 
 "Charting'colorfunctionScale", "Charting'CompleteSizes", 
 "Charting'computeScenePlotRange", "Charting'computeSceneRange", 
 "Charting'ConstructColorFunction", "Charting'ConstructDirective", 
 "Charting'ConstructErrorBars", "Charting'constructLegends", 
 "Charting'CoordinateListQ", "Charting'CoordinateQ", 
 "Charting'createDefaultLabels", "Charting'createPlotRange", 
 "Charting'createPlotRange3D", "Charting'dataExtremes", 
 "Charting'DateAxis", "Charting'datedDataExtremes", 
 "Charting'DateFormat", "Charting'DateScale", "Charting'DateScope", 
 "Charting'DateValueParser", "Charting'dbPrint", 
 "Charting'DefaultPlotStyle", "Charting'DisplayFunctionTest", 
 "Charting'DivisionLabelingFunction", "Charting'drawLegendMarkers", 
 "Charting'drawLegends", "Charting'drawMarkers", 
 "Charting'drawMarkers3D", "Charting'DynamicAction", 
 "Charting'DynamicImage", "Charting'edgeDirective", 
 "Charting'emptyDataQ", "Charting'ErrorBar", 
 "Charting'ErrorBarFunction", "Charting'ErrorBarSize", 
 "Charting'ErrorBarStyle", "Charting'expandFilling", 
 "Charting'expandPlaced", "Charting'expandPlotRange", 
 "Charting'expandPlotRange3D", "Charting'extractLabels", 
 "Charting'FilterGraphics3DOptions", "Charting'FilterGraphicsOptions", 
 "Charting'FinancialIndicatorList", 
 "Charting'FinancialIndicatorLists", "Charting'FinancialIndicators", 
 "Charting'FinancialPattern", "Charting'findAxesOrigin", 
 "Charting'FindGrid", "Charting'findPlotRange", "Charting'FindTicks", 
 "Charting'FindTicksP", "Charting'gaugeBoxes", "Charting'GaugeCheck", 
 "Charting'generalDirective", 
 "Charting'generateLegendDynamicVariable", "Charting'generateLegends", 
 "Charting'get2DPlotRange", "Charting'get3DPlotRange", 
 "Charting'getBasicStyles", "Charting'getBasicStyles2", 
 "Charting'getDataExtremes", "Charting'getExtremes", 
 "Charting'GetGraphicsOptions", "Charting'getPlotStyles", 
 "Charting'getQuantityLabel", "Charting'getSideMarker", 
 "Charting'getTargetUnits", "Charting'getTrendStyle", 
 "Charting'gridlinesFinder", "Charting'HeldOptionQ", 
 "Charting'Highlighted", "Charting'HistArgCheck", 
 "Charting'HorizontalScale", "Charting'iBarChart", 
 "Charting'iBarChart3D", "Charting'iBarLegend", 
 "Charting'iBoxWhiskerChart", "Charting'iBubbleChart", 
 "Charting'iBubbleChart3D", "Charting'iCandlestickChart", 
 "Charting'iDensityHistogram", "Charting'iDialGauge", 
 "Charting'iDistributionChart", "Charting'iFinancialIndicatorLists", 
 "Charting'iHistogram", "Charting'iHistogram3D", 
 "Charting'iHistogramList", "Charting'iInteractiveTradingChart", 
 "Charting'iKagiChart", "Charting'iLegended", "Charting'iLinearGauge", 
 "Charting'iLineBreakChart", "Charting'iLineLegend", 
 "Charting'IndicatorFunction", "Charting'Indicators", 
 "Charting'interactiveTradingChartActionMenu", 
 "Charting'interactiveTradingChartResetButton", 
 "Charting'interactiveTradingChartSnapshotButton", 
 "Charting'iPairedBarChart", "Charting'iPairedHistogram", 
 "Charting'iPointFigureChart", "Charting'iPointLegend", 
 "Charting'iRenkoChart", "Charting'iSectorChart", 
 "Charting'iSectorChart3D", "Charting'iSwatchLegend", 
 "Charting'iTradingChart", "Charting'LabelSide", "Charting'Legend", 
 "Charting'LegendCanvas", "Charting'LegendConstructer", 
 "Charting'legendize", "Charting'LegendSize", 
 "Charting'LegendWrapper", "Charting'listDepthCount", 
 "Charting'ListScale", "Charting'lookUpIndicators", 
 "Charting'mainChart", "Charting'makeDynamicModule", 
 "Charting'makeGaugeBoxes", "Charting'MemoryLeakTest", 
 "Charting'MouseEffect", "Charting'nearestDate", "Charting'negativeQ", 
 "Charting'nonNegativeQ", "Charting'noShow", "Charting'Nothing", 
 "Charting'OHLC", "Charting'OHLCV", "Charting'optCheck", 
 "Charting'padChartElements", "Charting'PadLabels", 
 "Charting'padList", "Charting'padMarkerStyle", 
 "Charting'padMarkerStyle2", "Charting'padMarkerStyle3", 
 "Charting'PairedCategoryAxis", "Charting'PairedChartArgCheck", 
 "Charting'PairedHistArgCheck", "Charting'ParametricScale", 
 "Charting'parseBulletChart", "Charting'parseChartElements", 
 "Charting'parseChartElementsRow", "Charting'parseChartLabels", 
 "Charting'parseChartLabelsRow", "Charting'parseChartLegends", 
 "Charting'parseChartLegends2", "Charting'parseClock", 
 "Charting'parseLabelingFunction", "Charting'parseLegendPlotStyle", 
 "Charting'parsePlotMarkers", "Charting'parsePlotMarkers3D", 
 "Charting'parseThermometer", "Charting'PatternsFunction", 
 "Charting'PFLP", "Charting'PictorialBar", "Charting'PictorialBar3D", 
 "Charting'PictorialBubble", "Charting'PictorialBubble3D", 
 "Charting'PictorialTrap", "Charting'PlainAutomaticBar3D", 
 "Charting'PlotArgCheck", "Charting'PlotOrigin", 
 "Charting'PlotParser", "Charting'PlotTheme", 
 "Charting'polarMarkerLabeling", "Charting'polarMarkerLabeling3D", 
 "Charting'polygonDirective", "Charting'positiveQ", 
 "Charting'PruneOptions", "Charting'RadialScale", 
 "Charting'RangeBarChart", "Charting'realNumericQ", 
 "Charting'RenderAssembler", "Charting'RenderMarker", 
 "Charting'RenderMouseEffect", "Charting'rescale", 
 "Charting'resetAngle", "Charting'resolveHighlighting", 
 "Charting'resolveLabeled", "Charting'resolveLabeledDynamic", 
 "Charting'resolveLabeledStatic", "Charting'resolveLabelingFunction", 
 "Charting'resolveLabelingFunctionDynamic", 
 "Charting'resolveLabelingFunctionStatic", 
 "Charting'resolveMarkerLabeling", "Charting'resolvePlaced", 
 "Charting'resolvePlacedDynamic", "Charting'resolvePlacedStatic", 
 "Charting'resolvePlotRangePadding", "Charting'ResolvePlotTheme", 
 "Charting'RotateLabels", "Charting'RotateTicks", "Charting's", 
 "Charting'safeColor", "Charting'ScaleAxes", "Charting'ScaleAxis", 
 "Charting'ScaleAxis3D", "Charting'ScaledFrameTicks", 
 "Charting'ScaledTicks", "Charting'ScaledTicks2", 
 "Charting'ScaledTickValues", "Charting'scaledValues", 
 "Charting'scientificForm", "Charting'SetChartStyleInformation", 
 "Charting'SimplePadding", "Charting'StudiesFunction", 
 "Charting'styleTree", "Charting's$", "Charting'TickAnnotations", 
 "Charting'TickLabels", "Charting'TickLengths", 
 "Charting'TickMarkers", "Charting'TickSide", "Charting'TickWrappers", 
 "Charting'TimeAxis", "Charting'TimelineParser", "Charting'TimeScale", 
 "Charting'tradingChartGridlinesFinder", 
 "Charting'TradingChartIndicator", "Charting'TradingChartSlider", 
 "Charting'Tukey5", "Charting'Tweaked", "Charting'unitConverting", 
 "Charting'UnsetChartStyleInformation", "Charting'value2pts", 
 "Charting'valueToAngle", "Charting'varCheck", 
 "Charting'VerticalScale", "Charting'$Graphics3DExtraOptions", 
 "Charting'$GraphicsExtraOptions", "Charting'$MajorTickLength", 
 "Charting'$MinorTickLength", "Charting'$PlotTheme", 
 "Charting'$PlotThemes"} 

So maybe there is some chance left to regain control over our plots. However, this is beyond me. Please, could somebody explain to me the reasoning behind the new Legended functionality and the Layout? What were they thinking??


1
[+13] [2012-11-28 23:14:50] Sjoerd C. de Vries

If you provide BarLegend as an explicit option value of PlotLegends it seems to do what you want:

DensityPlot[Sin[x] Sin[y], {x, -4, 4}, {y, -3, 3}, 
 ImageSize -> {300, 300}, PlotLegends -> BarLegend["LakeColors"]]

Mathematica graphics


(5) almost... it's now offset vertically. - rm -rf
(22) @rm-rf That will surely be fixed by version 18... - Jens
(1) @Jens I almost chocked on my noodles laughing ... - Gabriel
(1) @Jens At least, in version 11. This is fixed. And explict Barlegend is not the key. ImageSize is the key that must be explicitly set ! It seems that BarLegends needs ImageSize to pick up LegendMarkerSize. Check DensityPlot[Sin[x] Sin[y], {x, -4, 4}, {y, -3, 3}, ImageSize -> Medium, PlotLegends -> Automatic] - matheorem
@Jens Well, I found I am wrong. With different plot ticks and legend ticks(the number of ticks are varying with different plot range). There is sometimes perfect match, most time slight offset... - matheorem
@matheorem It works for the example you gave - looks like ImageSize is very often the answer when plots look bad, especially after exporting... but I guess we'll still have to wait for version 18 after all. - Jens
2
[+11] [2012-11-29 00:59:17] WalkingRandomly

This makes me happy. Still a usage case for ye-olde-colorbarplot package :) I've not checked if it works in v9 though!

http://www.walkingrandomly.com/?p=2960


I have tested tested colorplot package with v9 from walkingrandomly.com/?p=2960 everything works just fine, thanks. - Tuku
3
[+10] [2012-11-29 21:27:54] MinHsuan Peng

Hope this workaround helps.

Use Placed to position legends more precisely:

DensityPlot[Sin[x] Sin[y], {x, -4, 4}, {y, -3, 3}, 
 PlotLegends -> 
  Placed[BarLegend[Automatic, LegendMarkerSize -> 280], {1.05, 0.52}]]

enter image description here

{1.05, 0.52} is a scaled position referred to the DensityPlot.

The offset here, 0.52 instead of 0.5, is because frame tick labels move the plot off center. The same reasoning applies to the BarLegend itself sometimes because the tick labels can move the gradient off center (this example is lucky to have symmetric labels on both ends).

LegendMarkerSize->280 is because the DensityPlot has some plot range padding that needs compensation.


Can you add more Details on how you obtained the values (0.02 offset, the 1.05and the 280)? - Ronny
I guess those offsets are just hand chosen... but this is good to know anyway. This is a good option for one-off cases I think. - Andrew Moylan
(1) I wonder if an Aligned[...] wrapper could be created, by analogy with Placed[...]. Aligned[expr, Top, tag] tries to align the Top of expr with other Aligned elements with the same tag. - Andrew Moylan
@Andrew Right, it is difficult to get the number right programmatically because.. 1. PlotRangePadding is by default Scaled. 2. LabelStyle can also affect the ticks label size both in plots and BarLegend. - MinHsuan Peng
Ok, i just played around with my example for the PlotLegends and guessed them, too; though they are quite different for my ArrayPlot (that does not have Padding for example). - Ronny
(1) @Ronny, 1.05 means Scaled[1.05] refer to the plot. Scaled[{0,0}] is left bottom corner of the plot and Scaled[{1,1}] is right top corner. A double list give you full control. {pos_list, objpos_list} - MinHsuan Peng
@AndrewMoylan and MinHsuan: This answer might help you get the padding programmatically. I've used it a few times to align two plots precisely like in this answer - rm -rf
4
[+6] [2016-12-07 05:43:17] Felix

There is a way to combine the already suggested old style Row arrangement (see here [1]) automatically with the new and convenient BarLegend using these conversion function:

(* Function to generate the color bar legend *)

customBarLegend[zmin_, zmax_, label_, colorFunction_: Automatic, 
  colorFunctionScaling_: True] := Module[{},
  Show[ArrayPlot[
    Table[{zmax + zmin - y}, {y, zmin, zmax, (zmax - zmin)/100}],
    ColorFunction -> colorFunction,
    ColorFunctionScaling -> colorFunctionScaling,
    DataRange -> {{0, 1}, {zmin, zmax}},
    Frame -> True,
    FrameLabel -> {{None, None}, {None, label}},
    FrameTicks -> {{None, All}, {None, None}},
    PlotRangePadding -> 0,
    AspectRatio -> 20,
    Axes -> False],
   PlotRange -> {{0, 1}, {zmin, zmax}}]]

(* Function to convert a regular (ugly) BarLegend into a custom bar 
legend that has the same height as the plot. *)

convertBarLegend[plot_, imPad_, barPad_, size_] := 
 Module[{zmin, zmax, zlabel, colorFunction, colorFunctionScaling, bar},
  {zmin, zmax} = (List @@ (List @@ plot)[[2]][[1]])[[1]][[2]];
  zlabel = LegendLabel /. (List @@ (List @@ plot)[[2]][[1]])[[3]];
  colorFunction = (List @@ (List @@ plot)[[2]][[1]])[[1]][[1]];
  colorFunctionScaling = 
   ColorFunctionScaling /. (List @@ (List @@ plot)[[2]][[1]])[[6]];
  bar = customBarLegend[zmin, zmax, zlabel, colorFunction, 
    colorFunctionScaling];
  Row[{Show[(List @@ plot)[[1]], ImageSize -> {Automatic, size}, 
     ImagePadding -> imPad], 
    Show[bar, ImageSize -> {Automatic, size}, ImagePadding -> barPad]}]
  ]

Example:

uglyplot = 
 DensityPlot[Sin[x] Sin[y], {x, -4, 4}, {y, -3, 3}, 
  PlotLegends -> BarLegend[Automatic, LegendLabel -> "z"]]

default image style

imPad = {{50, 7}, {60, 10}}; (*{{left,right},{bottom,top}}*)
barPad = {{1, 100}, imPad[[2]]};(* bottom and top should be the same as imPad. *)
plot = convertBarLegend[uglyplot, imPad, barPad, 300]

consistent bar height

The numbers in imPad and barPad need to be adjusted to fit the size of the tick labels and the axes/frame labels. Therefore, they depend on the actual labels. The last parameter size determines how large the image is rendered.

In the functions, I make use of the fact that List@@plot gives access to a large variety of parameters that characterize the plot, such as ranges and labels.

Edit:

Changed the rendering of the custom bar legend from DensityPlot to ArrayPlot. This reduces the computation time and the file size of the graphics if exported to disk. Similarly, it is recommended to use ArrayPlot for the main graphics. See here [2] for an example.

[1] https://mathematica.stackexchange.com/questions/2058/sizing-cells-in-a-graphicsgrid-graphicsrow/2064#2064
[2] https://mathematica.stackexchange.com/questions/133021/export-grid-of-figures-not-graphicsgrid-to-pdf

5
[+3] [2018-05-09 03:12:37] matheorem

Here is my attempt to solve it as a post-processing way.

I will use two tools as bridges

  1. convert legend to graphics from Kuba [1]
  2. get absolute padding from Heike [2]

The basic idea is stated quite clearly in Szabolcs's answer [3] for frame plots.

So first is define convertLegendToGraphics, it converts legend to Graphics object.

ClearAll[convertLegendToGraphics];
convertLegendToGraphics[legend_] := 
 First@Cases[ToBoxes@legend, 
   gr_GraphicsBox :> ToExpression[gr], \[Infinity]]

Then define getPadding

ClearAll[getPadding];
getPadding[g_] := Module[{im},
   labelStyleOpt = Options[g, LabelStyle][[1, 2]];
   im = Image[
     Show[g /. _?ColorQ -> White, 
      LabelStyle -> Directive[labelStyleOpt, White], 
      Background -> White]];
   BorderDimensions[im] + {{0, 1}, {1, 0}}];

Note that I do a little tweak here which I found is necessary if your plot has specified custom LabelStyle or Styled PlotLabel. The _?ColorQ -> White has the ability to turn any explicit colored things into white including explicitly colored PlotLabel. However, it will have an disadvantage, it make getPadding only works for black frame or axis, so do not set fancy colored frame or axis.

then, finally the main part

ClearAll[sameHeightLegends];
sameHeightLegends[plot_] := Module[{},
  plotPart = plot[[1]];
  plotLabelOpt = Options[plotPart, PlotLabel][[1, 2]];
  imageSize = ImageDimensions[plotPart];
  verticalImageSize = imageSize[[2]];
  legendPart = 
   Show[convertLegendToGraphics@plot[[2, 1]], 
    ImageSize -> {Automatic, verticalImageSize}];

  {ph, pv} = getPadding[plotPart];
  {phNoLabel, pvNoLabel} = 
   getPadding[Show[plotPart, PlotLabel -> None]];
  {lh, lv} = getPadding[legendPart /. _?ColorQ -> White];
  verticalPadding = pv;
  If[plotLabelOpt === None,
   Row[{Show[plotPart, ImageSize -> imageSize, 
      ImagePadding -> {ph, verticalPadding}], 
     Show[legendPart, ImagePadding -> {lh, verticalPadding}]}],
   Row[{Show[plotPart, ImageSize -> imageSize, 
      ImagePadding -> {phNoLabel, pvNoLabel}], 
     Show[legendPart, ImagePadding -> {lh, verticalPadding}]}]]]

note that I treat labeled case separately.

Ok, here is an example which I found probably no other solutions can done it right.

plot = DensityPlot[x, {x, 0, 1}, {y, 0, 1},
  PlotLabel -> Style[Column[{"line1", "line2"}], 30, Red],
  BaseStyle -> Directive[Bold, 24],
  FrameLabel -> {"x", "y"}, LabelStyle -> Green,
  PlotLegends -> Automatic]

it will give

enter image description here

and

sameHeightLegends[plot]

gives

enter image description here

ps

This method doesn't need to set ImageSize explictly and no special treatment to PlotLegends, so is full automatic.

But of course, it only supports vertical Legends.

Currently, this post-processing method has one drawback. To retrieve absolute dimension of Plot or absolute ImagePadding, we need rasterization, and every rasterization takes about 0.3 seconds on my computer, so it has some efficiency problem. Nevertheless, for most case, it is bearable. Hope there is some faster way to get absolute imagesize and imagepadding.

[1] https://mathematica.stackexchange.com/a/172823/4742
[2] https://mathematica.stackexchange.com/a/2093/4742
[3] https://mathematica.stackexchange.com/a/8660/4742

This works bad in v10.4, although it works almost good in v11.3 - except for some wiggly line directly below the legend. - corey979
@corey979 Thank you for comment. then I don't know what is going on? Mathematica is really a fast changing system! - matheorem
the "wiggly line" below barlegend only appears on linux from v11.3. see here for solutions. - Praan
6
[+2] [2012-11-29 20:43:10] j--

In the featured example on changing legend orientations [1], they use the following:

PlotLegends -> Placed[BarLegend[Automatic, LegendLayout -> "Column"], After]

This appears to produce legends that align as wanted if accompanied by an explicit ImageSize. It still produces a slight vertical offset as in Sjoerd's answer.

As a side note, the four-plot combination on the same page is far from perfect because of the other misalignments.

[1] http://reference.wolfram.com/mathematica/example/ChangeLegendOrientation.html

The options you mentioned seem - as far as i worked today with PlotLegends - to be the default values, hence they lead to exactely the image the OP postet. But Setting ImageSize -> 300 for the Plot will (why ever) do the Job on my PC (in contrary to @Sjoerd C.s answer), if I use only one Value and set the PlotRangePadding -> 0 - Ronny
7