Editor's Note: This file was selected as MATLAB Central Pick of the Week
This is a simple MATLAB function for axis label alignment. It still works when Projection mode is Perspective or when DataAspectRatio is not [1 1 1].
## Functions
 `align_axislabel`: it rotates $x$, $y$ and $z$ labels to the direction of their corresponding axes and moves the labels to a proper distance from the axes;
 `align_axislabel_log`: supports logscale in $z$ axis;
 `axislabel_rotation`: it performs rotation only;
 `axislabel_rotation_angle`: it computes the angles of $x$, $y$ and $z$ labels to be rotated properly (without performing the actual rotation);
 `axislabel_translation`: it moves axis labels to a proper distance from the axes;
 `axislabel_translation_slider`: a GUI slider for setting parameters `AXISALIGN_TRANS_A` and `AXISALIGN_TRANS_B`.
## Common usage
Label alignment plus GUI slider:
```
z = peaks;
figure('color', [1 1 1])
surf(z);
set(gca, 'dataaspectratio', [1 1 0.5], 'projection', 'perspective', 'box', 'on')
xlabel('This is an x label', 'fontsize', 16, 'fontweight', 'bold', 'color', [1 0 0])
ylabel('This is a y label', 'fontsize', 16, 'fontweight', 'bold', 'color', [0 0 0])
zlabel('This is a z label', 'fontsize', 16, 'fontweight', 'bold', 'color', [0 0 1])
% Add the following after you plot your figures
h = rotate3d;
set(h, 'ActionPreCallback', 'set(gcf,''windowbuttonmotionfcn'',@align_axislabel)')
set(h, 'ActionPostCallback', 'set(gcf,''windowbuttonmotionfcn'','''')')
set(gcf, 'ResizeFcn', @align_axislabel)
align_axislabel([], gca)
axislabel_translation_slider;
```
See `demo.m` for more information.
Ligong Han (2020). phymhan/matlabaxislabelalignment (https://github.com/phymhan/matlabaxislabelalignment), GitHub. Retrieved .
1.7.0.0   updates examples 

1.6.0.0   Adds GUI slider for parameter setting (controlling translation behaviour) 

1.5.0.0   Log scale on z axis 

1.5.0.0   Adds example for subplots 

1.5.0.0   Changes align_axislabel.m back to align_axislabels.m, sorry for the confusion


1.5.0.0   Adds check for class of 'ax' in align_axislabel.m


1.4.0.0   Adds a trans_mode option 

1.4.0.0   Revised for R2014b 

1.3.0.0   Modified the method to move labels to avoid potential overlap;


1.2.0.0   Modified the direction of axis label translation 

1.1.0.0   Added a function for translation

Inspired by: Align axes labels in 3D plot
Create scripts with code, output, and formatted text in a single executable document.
hi @Ligong Han, it has some mistake when it is used in the function "bar3" in the matlab, i need you help
Thank you for sharing. The function works well on Matlab_2018b.
Can use something simple like the following, adjust dx and dy as necessary.
dx = 0.5;
dy = 0.5;
x_axis_label_pos = get(xlh, 'Position');
x_axis_label_pos(1,1) = x_axis_label_pos(1,1) + dx;
x_axis_label_pos(1,2) = x_axis_label_pos(1,2) + dy;
set(xlh, 'Position', x_axis_label_pos);
Hi @mukund, you can follow the second example by add the following:
h = rotate3d;
set(h, 'ActionPreCallback', 'set(gcf,''windowbuttonmotionfcn'',@align_axislabel)')
set(h, 'ActionPostCallback', 'set(gcf,''windowbuttonmotionfcn'','''')')
set(gcf, 'ResizeFcn', @align_axislabel)
align_axislabel([], gca)
axislabel_translation_slider;
then you should be able to move labels by adjusting the sliders.
Thanks for sharing. The code works fine. I want labels to be slightly closer to axis. How this can be achieved.
Works fantastic on 2017a, thanks!
hi @Ligong Han. Thank you for you help. I tried the demo code below but xlabel and ylabel has not rotated to align. How can I solve this?
%% Demo of setting text properties
% Perspective, DataAspectRatio = [1 1 0.5]
z = peaks;
figure('color',[1 1 1])
surf(z);
set(gca,'dataaspectratio',[1 1 0.5],'projection','perspective','box','on')
xlabel('This is an x label','fontsize',16,'fontweight','bold','color',[1 0 0])
ylabel('This is a y label','fontsize',16,'fontweight','bold','color',[0 0 0])
zlabel('This is a z label','fontsize',16,'fontweight','bold','color',[0 0 1])
get(gca,'dataaspectratio')
set(gca,'dataaspectratio',ans)
h = rotate3d;
set(h,'ActionPostCallback',@align_axislabel)
Hi @Simon L, thanks for catching that. The code doesn't work because in your example the `YDir` property of the axes becomes 'reverse', and I haven't thought about this situation. A quick fix would be set `YDir` back to 'normal':
>> set(gca, 'ydir', 'normal');
This is of course not an elegant solution. I might update the code sometime.
Hi @Ligong Han ! This tool does not work correctly with the function "bar3" (I have Matlab R2016b in Win64).
The xlabel, ylabel and zlabel are rotated correctly, but they are close to the wrong axis.
To better understand what I mean please check your example by using "bar3(z)" instead of "surf(z)".
Here following the code. What do you think ?
Limo
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
z = peaks;
figure('color', [1 1 1])
% surf(z);
bar3(z);
set(gca, 'dataaspectratio', [1 1 0.5], 'projection', 'perspective', 'box', 'on')
xlabel('This is an x label', 'fontsize', 16, 'fontweight', 'bold', 'color', [1 0 0])
ylabel('This is a y label', 'fontsize', 16, 'fontweight', 'bold', 'color', [0 0 0])
zlabel('This is a z label', 'fontsize', 16, 'fontweight', 'bold', 'color', [0 0 1])
% Add the following after you plot your figures
h = rotate3d;
set(h, 'ActionPreCallback', 'set(gcf,''windowbuttonmotionfcn'',@align_axislabel)')
set(h, 'ActionPostCallback', 'set(gcf,''windowbuttonmotionfcn'','''')')
set(gcf, 'ResizeFcn', @align_axislabel)
align_axislabel([], gca)
axislabel_translation_slider;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Still do not work if axis are not equal....
Hi @Caster Troy, thanks for comments. If only z axis is log scale, there's a quick fix. I added align_axislabel_log.m (please see the 4th example above).
Hi @Leo Simon, thanks for comments. Please see the latest example for subplots.
Thanks very much for this contribution, I've been wanting something like this for a *long* time. It's seems to be having trouble with subplots, as the following example code illustrates. Alignment for the full plot is perfect, but is off for the subplot. Do you have a fix for this? Thanks! Leo
Z = peaks;
surf(Z);
xlabel('x label');
ylabel('y label');
zlabel('z label');
ax = struct('Axes', gca);
align_axislabels([],ax)
figure
subplot(2,1,1);
surf(Z);
xlabel('x label');
ylabel('y label');
zlabel('z label');
ax = struct('Axes', gca);
align_axislabels([],ax)
Function doesn't work correct, when axes are log :(
Hi @Oscar, sorry I don't have MATLAB 2016a available for testing, but your code works on my 2015a (Win64).
Thanks for your quick response.
Well, I tried that but then the labels disappear. I am using Matlab 2016a on Win64 if it matters.
 code
figure
axes;
xlabel('x')
ylabel('y')
zlabel('z')
n = 90;
el = 30*ones(1, n);
az = linspace(0, 180, n);
ax = struct('Axes', gca);
for k = 1:n
view([az(k) el(k)]);
align_axislabels([], ax)
drawnow
pause(0.1)
end
/code
Thanks
/Oscar
Hi @Oscar, sorry for the confusion of the function naming. You can just call align_axislabels instead of axislabel_rotation. Then labels would be rotated and translated.
For example,
n = 100;
el = 30*ones(1, n);
az = linspace(0, 180, n);
ax = struct('Axes', gca);
for k = 1:n
view([az(k) el(k)]);
align_axislabels([], ax)
pause(0.1)
end
Hi
I want to use this code to automatically align the labels from the code. I have a loop that changes the view for every iteration and I want the labels to change with the angle.
I tried to call
'axislabel_rotation([],gca)'
and in the function set
'h_a=gca;'
on row 16.
It kind of works, but the zlabel gets really close to the zaxis and the fix you mentioned below does not work since the function 'axislabel_translation.m' is not called at all.
Also, the letters in the labels seem to jump a bit so that they are not relly aligned to eachother. But maybe this is how it is?
Regards
Oscar
Hi @Jianwei Tu, thank you for the feedback. For your question, a quick fix is to reset the DataAspectRatio of your plot (or axes to be precise). For example, you can add the following line in your code:
>> set(gca,'DataAspectRatio', get(gca,'DataAspectRatio'))
The problem seems to be caused by some strange behavior when MATLAB renders a picture. You can do a quick experiment here:
Plot a surface, and add x y labels:
>> surf(peaks); xlabel('this is an x label'); ylabel('this is a y label');
Get the data aspect ratio of the axes:
>> get(gca,'dataaspectratio')
Now if you set 'dataaspectratio' as the same value as what it is previously, your plot will change:
>> set(gca,'dataaspectratio',ans)
I think this is the reason why axis labels are misaligned in your case, but I don't know why it happens. A common practice is to always set the 'DataAspectRatio' to some value explicitly, so that the labels should be aligned nicely. Thanks!
@Ligong Han, Thank you for your answer. Your first suggestion works well to solve the z axis label problem that I had. But the x and y axis label alignment issue still exists. I am not an expert at all in Matlab. When I run the example you gave here, the x and y axis labels were fine, but when I run the following codes:
figure
X = linspace(0,1,10);
Y = X./2;
Z = sin(X) + cos(Y);
stem3(X,Y,Z,'fill')
xlabel('This Is Going to Be a Long Title!');
ylabel('This Is Going to Be a Long Title!');
zlabel('This Is Going to Be a Long Title!');
h = rotate3d;
set(h,'ActionPostCallback',@align_axislabels)
and rotated the 3D plot to (Az:45 El:45) position, both x and y axis labels formed a 1020 degree angle with x and y axes, instead of being parallel with them, which is really strange. I don't see too much difference in the example codes here and my given codes.
Hi @Jianwei Tu, thanks for your feedback! For your first question, you can comment out the code from line 259 to 261 in align_axislabels.m or always add 180 degrees to theta_z, if you wish; for the second question, how off are label and axis misaligned? I'm not sure why this happens but theoretically the calculation should be correct. If you have any questions please let me know. Thanks.
Hi @Ligong Han, This is great work you have done!! Exactly what I am looking for!
I had the same issue as Anthony did with larger font size label coinciding with label ticks, but I fixed it using your suggestion, i.e., increasing the A and B values.
However, I also found that after I rotate the 3D figures, (1.) z axis label got turned 180 degrees around its center, and (2) the x and y labels were not exactly aligned with x and y axes. What would you suggest to fix these two problems?
Thank you so much again for your great work!!!
Hi, @jasongrig, thanks for your comment. What do you mean by "all over the place"? I haven't tested it on 2013a.
hi, i am afraid your function does not work on matlab R2013a. I copypasted your example in the description and the labels are all over the place. Any ideas?
Thanks @Anthony There are two parameters you can change to avoid this problem: you can adjust (increase) the value of A and B in line 42 and 43 in axislabel_translation.m (the latest version), for example, A = 1.25, B = 3. The definition of A and B is in line 41.
Very nice job, thanks a lot for sharing this :)
There is only a minor problem (I am using R2015a): when I increase the font size, the labels cover the axes TickLabels. I guess it is very hard to take into account all the possibilities. Is there a way to manually control the spacing between the label and the ticklabels (or is there a parameter I could change in your code)?
Thanks @4st4rl04 It's true that axis labels appear only if you rotate the figure manually. But it is because you set 'projection' to 'perspective'. If you don't want to change the default view angle, you can click the 'Rotate 3D' button and click the figure rather than rotate it so that the callback function will be called without changing the azimuth and elevation of view.
Hi, this doesn't seem to work on MATLAB 2014a on my Mac. The figure of the example only shows the labels once I rotate the figure manually, and it looks funny even then.