MATLAB | Leyenda de amor y Leyenda redondeada translúcida exquisita

Todos los diagramas de este artículo son de elaboración propia, por favor indique la fuente al momento de difundirlos.

Escribí algunas pequeñas funciones terminadas, como convertir el icono de la leyenda en forma de corazón al dibujar un gráfico circular:

Por ejemplo, cómo hacer una leyenda redondeada semitransparente:

Todavía hable sobre el principio primero y luego dé estos dos códigos:


1 Explicación del principio - Objeto gráfico

objeto cuadrilátero cerrado

En el artículo anterior ya hemos hablado de las propiedades ocultas del componente leyenda:

El contorno y, en la mayoría de los casos, la leyenda se dibujan LineLooputilizando :Quadrilateral

Estos dos objetos gráficos básicos dibujan gráficos en grupos de cuatro puntos, y el principio general es el siguiente:

VertexDataSon las coordenadas de los vértices. Es una matriz de tamaño 3xn. La primera fila representa las coordenadas x, y las filas 2 y 3 representan las coordenadas y y z. El rango es 0-1.

Cada cuatro puntos es un grupo, por ejemplo, si hay ocho vértices, cuatro cuatro vértices se agruparán en un gráfico (1,2,3,4 un grupo, 5,6,7,8 un grupo):

Por supuesto, puede organizar los puntos en orden o establecer VertexIndicesel orden de los vértices para obtener la forma de cuadrilátero deseada:


otros objetos

En comparación con el objeto que solo puede ser un grupo de cuatro puntos, también presentamos un objeto más flexible. En primer lugar LineStrip, este objeto gráfico dibujará una línea en grupos de dos puntos:

En cambio TriangleStrip, un grupo de tres puntos dibuja un objeto que llena un triángulo, por ejemplo, un polígono complejo se puede llenar con varios triángulos:


2 Principio Explicación - Creación y Reemplazo

Permítanme hablar sobre cómo construir objetos gráficos básicos. Estos objetos se construyen mediante funciones no reveladas de muy bajo nivel, por ejemplo LineStrip, no a través de:

  • LineStrip ()

para construir, pero a través de:

  • matlab.graphics.primitive.world.LineStrip()

Después de construir el objeto, se deben establecer las siguientes propiedades para que se muestre el objeto oculto:

  • Capa
  • Encuadernación de colores
  • ColorData
  • VertexData
  • PickableParts

La configuración de estas propiedades puede referirse a la leyenda original para formar el objeto, que no se describirá en detalle aquí, pero también se refiere al código que escribí.

A continuación, establezca la clase principal del objeto recién construido en la clase principal de grupo del componente original y, a continuación, oculte el componente original:

newBoxEdgeHdl.Parent=oriBoxEdgeHdl.Parent;
oriBoxEdgeHdl.Visible='off';

Lo anterior es todo el proceso de reemplazo de componentes, y escribí dos piezas de código de muestra:


3 código de muestra

leyenda translúcida

function SPrettyLegend(lgd)
% Semitransparent rounded rectangle legend
% Copyright (c) 2023, Zhaoxu Liu / slandarer
% -------------------------------------------------------------------------
% Zhaoxu Liu / slandarer (2023). pretty legend 
% (https://www.mathworks.com/matlabcentral/fileexchange/132128-pretty-legend), 
% MATLAB Central File Exchange. 检索来源 2023/7/9.
% =========================================================================
if nargin<1
    ax = gca;
    lgd = get(ax,'Legend');
end
pause(1e-6)
Ratio = .1;
t1 = linspace(0,pi/2,4); t1 = t1([1,2,2,3,3,4]);
t2 = linspace(pi/2,pi,4); t2 = t2([1,2,2,3,3,4]);
t3 = linspace(pi,3*pi/2,4); t3 = t3([1,2,2,3,3,4]);
t4 = linspace(3*pi/2,2*pi,4); t4 = t4([1,2,2,3,3,4]);
XX = [1,1,1-Ratio+cos(t1).*Ratio,1-Ratio,Ratio,Ratio+cos(t2).*Ratio,...
    0,0,Ratio+cos(t3).*Ratio,Ratio,1-Ratio,1-Ratio+cos(t4).*Ratio];
YY = [Ratio,1-Ratio,1-Ratio+sin(t1).*Ratio,1,1,1-Ratio+sin(t2).*Ratio,...
    1-Ratio,Ratio,Ratio+sin(t3).*Ratio,0,0,Ratio+sin(t4).*Ratio];
% 圆角边框(border-radius)
oriBoxEdgeHdl = lgd.BoxEdge;
newBoxEdgeHdl = matlab.graphics.primitive.world.LineStrip();
newBoxEdgeHdl.AlignVertexCenters = 'off';
newBoxEdgeHdl.Layer = 'front';
newBoxEdgeHdl.ColorBinding = 'object';
newBoxEdgeHdl.LineWidth = 1;
newBoxEdgeHdl.LineJoin = 'miter';
newBoxEdgeHdl.WideLineRenderingHint = 'software';
newBoxEdgeHdl.ColorData = uint8([38;38;38;0]);
newBoxEdgeHdl.VertexData = single([XX;YY;XX.*0]);
newBoxEdgeHdl.Parent=oriBoxEdgeHdl.Parent;
oriBoxEdgeHdl.Visible='off';
% 半透明圆角背景(Semitransparent rounded background)
oriBoxFaceHdl = lgd.BoxFace;
newBoxFaceHdl = matlab.graphics.primitive.world.TriangleStrip();
Ind = [1:(length(XX)-1);ones(1,length(XX)-1).*(length(XX)+1);2:length(XX)];
Ind = Ind(:).';
newBoxFaceHdl.PickableParts = 'all';
newBoxFaceHdl.Layer = 'back';
newBoxFaceHdl.ColorBinding = 'object';
newBoxFaceHdl.ColorType = 'truecoloralpha';
newBoxFaceHdl.ColorData = uint8(255*[1;1;1;.6]);
newBoxFaceHdl.VertexData = single([XX,.5;YY,.5;XX.*0,0]);
newBoxFaceHdl.VertexIndices = uint32(Ind);
newBoxFaceHdl.Parent = oriBoxFaceHdl.Parent;
oriBoxFaceHdl.Visible = 'off';
end

Ejemplo de uso

clc; clear; close all
rng(12)
% 生成随机点(Generate random points)
mu = [2 3; 6 7; 8 9];
S  = cat(3,[1 0; 0 2],[1 0; 0 2],[1 0; 0 1]);
r1 = abs(mvnrnd(mu(1,:),S(:,:,1),100));
r2 = abs(mvnrnd(mu(2,:),S(:,:,2),100));
r3 = abs(mvnrnd(mu(3,:),S(:,:,3),100));
% 绘制散点图(Draw scatter chart)
hold on
propCell = {
    
    'LineWidth',1.2,'MarkerEdgeColor',[.3,.3,.3],'SizeData',60};
scatter(r1(:,1),r1(:,2),'filled','CData',[0.40 0.76 0.60],propCell{
    
    :});
scatter(r2(:,1),r2(:,2),'filled','CData',[0.99 0.55 0.38],propCell{
    
    :});
scatter(r3(:,1),r3(:,2),'filled','CData',[0.55 0.63 0.80],propCell{
    
    :});
% 增添图例(Draw legend)
lgd = legend('scatter1','scatter2','scatter3');
lgd.Location = 'northwest';
lgd.FontSize = 14;
% 坐标区域基础修饰(Axes basic decoration)
ax=gca; grid on
ax.FontName   = 'Cambria';
ax.Color      = [0.9,0.9,0.9];
ax.Box        = 'off';
ax.TickDir    = 'out';
ax.GridColor  = [1 1 1];
ax.GridAlpha  = 1;
ax.LineWidth  = 1;
ax.XColor     = [0.2,0.2,0.2];
ax.YColor     = [0.2,0.2,0.2];
ax.TickLength = [0.015 0.025];
% 隐藏轴线(Hide XY-Ruler)
pause(1e-6)
ax.XRuler.Axle.LineStyle = 'none';
ax.YRuler.Axle.LineStyle = 'none';

SPrettyLegend(lgd)


Leyenda en forma de corazón (exclusiva para gráficos circulares)

function pie2HeartLegend(lgd)
% Heart shaped legend for pie chart
% Copyright (c) 2023, Zhaoxu Liu / slandarer
% =========================================================================
if nargin<1
    ax = gca;
    lgd = get(ax,'Legend');
end
pause(1e-6)
% 心形曲线(Heart curve)
x = -1:1/100:1;
y1 = 0.6 * abs(x) .^ 0.5 + ((1 - x .^ 2) / 2) .^ 0.5;
y2 = 0.6 * abs(x) .^ 0.5 - ((1 - x .^ 2) / 2) .^ 0.5;
XX = [x, flip(x),x(1)]./3.4+.5;
YY = ([y1, y2,y1(1)]-.2)./2+.5;
Ind = [1:(length(XX)-1);2:length(XX)];
Ind = Ind(:).';
% 获取图例图标(Get Legend Icon)
lgdEntryChild = lgd.EntryContainer.NodeChildren;
iconSet = arrayfun(@(lgdEntryChild)lgdEntryChild.Icon.Transform.Children.Children,lgdEntryChild,UniformOutput=false);
% 基础边框句柄(Base Border Handle)
newEdgeHdl = matlab.graphics.primitive.world.LineStrip();
newEdgeHdl.AlignVertexCenters = 'off';
newEdgeHdl.Layer = 'front';
newEdgeHdl.ColorBinding = 'object';
newEdgeHdl.LineWidth = .8;
newEdgeHdl.LineJoin = 'miter';
newEdgeHdl.WideLineRenderingHint = 'software';
newEdgeHdl.ColorData = uint8([38;38;38;0]);
newEdgeHdl.VertexData = single([XX;YY;XX.*0]);
newEdgeHdl.VertexIndices = uint32(Ind);
% 基础多边形面句柄(Base Patch Handle)
newFaceHdl = matlab.graphics.primitive.world.TriangleStrip();
Ind = [1:(length(XX)-1);ones(1,length(XX)-1).*(length(XX)+1);2:length(XX)];
Ind = Ind(:).';
newFaceHdl.PickableParts = 'all';
newFaceHdl.Layer = 'middle';
newFaceHdl.ColorBinding = 'object';
newFaceHdl.ColorType = 'truecoloralpha';
newFaceHdl.ColorData = uint8(255*[1;1;1;.6]);
newFaceHdl.VertexData = single([XX,.5;YY,.5;XX.*0,0]);
newFaceHdl.VertexIndices = uint32(Ind);
% 替换图例图标(Replace Legend Icon)
for i = 1:length(iconSet)
    oriEdgeHdl = iconSet{
    
    i}(1);
    tNewEdgeHdl = copy(newEdgeHdl);
    tNewEdgeHdl.ColorData = oriEdgeHdl.ColorData;
    tNewEdgeHdl.Parent = oriEdgeHdl.Parent;
    oriEdgeHdl.Visible = 'off';

    oriFaceHdl = iconSet{
    
    i}(2);
    tNewFaceHdl = copy(newFaceHdl);
    tNewFaceHdl.ColorData = oriFaceHdl.ColorData;
    tNewFaceHdl.Parent = oriFaceHdl.Parent;
    oriFaceHdl.Visible = 'off';
end
end

Ejemplo de uso

clc; clear; close all
% 生成随机点(Generate random points)
X = [1 3 0.5 2.5 2];
pieHdl = pie(X);

% 修饰饼状图(Decorate pie chart)
colorList=[0.4941    0.5490    0.4118
    0.9059    0.6510    0.3333
    0.8980    0.6157    0.4980
    0.8902    0.5137    0.4667
    0.4275    0.2824    0.2784];
for i = 1:2:length(pieHdl)
    pieHdl(i).FaceColor=colorList((i+1)/2,:);
    pieHdl(i).EdgeColor=colorList((i+1)/2,:);
    pieHdl(i).LineWidth=1;
    pieHdl(i).FaceAlpha=.6;
end
for i = 2:2:length(pieHdl)
    pieHdl(i).FontSize=13;
    pieHdl(i).FontName='Times New Roman';
end
lgd=legend('FontSize',13,'FontName','Times New Roman','TextColor',[1,1,1].*.3);

pie2HeartLegend(lgd)


encima

Lo anterior es toda la exploración realizada en este artículo. Debo ser la primera persona en toda la red en brindar un método factible para modificar la leyenda. A través del método anterior, el dibujo de leyendas especiales, como las leyendas de histogramas de sombras, también se ha hecho posible. Espero con ansias tu segunda ha creativa.

Supongo que te gusta

Origin blog.csdn.net/slandarer/article/details/131628250
Recomendado
Clasificación