阴影柱状图绘制的代码MATHWORKS上也有,不过是生成图片后,识别图像上不同颜色块并直接修改像素生成阴影线,这样的生成方式不可逆且自由度较低,因此本人开发了一个直接画线条填充的硬画版本。
另:由于不太想动脑子,使用polyshape
对象进行了交点判定,减少了代码出错的概率,但由于代码开发基于polyshape
对象,阴影柱状图绘制函数理论上需要至少R2017b
及之后版本才能使用(越新越好)。
由于工具函数过长,将被放在最后展示,以下将先展示函数用法。
示例图就短短三行代码就能画,真的简单:
y=[2 2 -3 -2 -5; -2 -5 6 2 5; 9 8 9 2 5];
SH=shadowHist(y,'ShadowType',{'/','\','.','x','|'});
SH=SH.draw();
使用legend
函数添加图例,使用方式如下:
y=[2 2 3 2 5; 2 5 6 2 5; 9 8 9 2 5];
SH=shadowHist(y,'ShadowType',{'/','\','.','_','+'});
SH=SH.draw();
SH=SH.legend({'AAAAAAA','BBBBBBB','CCCCCCC','DDDDDDD','EEEEEEE'},'FontName','Arial','FontSize',11);
图例是自行绘制的,能拖动及自动缩放(老难算了这玩意):
阴影有: \
,/
,_
,|
,+
,x
,.
,w
,k
,g
十种格式,以下全部展示一下:
y=[2 2 3 2 5 4 2 2 2 1;2 2 3 2 5 4 2 4 3 6];
SH=shadowHist(y,'ShadowType',{'/','\','x','.','_','|','+','w','k','g'});
SH=SH.draw();
SH=SH.legend({'A','B','C','D','E','F','G','H','I','J'});
含负数
y=[2 2 -3 -2 -5; -2 -5 6 2 5; 9 8 9 2 5];
SH=shadowHist(y,'ShadowType',{'/','\','.','x','|'});
SH=SH.draw();
堆叠柱状图
y=[2 2 -3 -2 -5; -2 -5 6 2 5; 9 8 9 2 5; -3 -5 6 2 5; 4 8 5 2 5];
SH=shadowHist(y,'ShadowType',{'/','\','.','x','|'},'stacked');
SH=SH.draw();
阴影、柱状图框、图例框分别具有barShadow
,barBox
,lgdBox
的标签,使用findobj
获取对象并循环修饰即可,不过为了绘制更好看,部分阴影使用plot
绘制部分则是使用scatter
绘制,因此阴影修饰时要用if先检测一下格式,给个示例:
y=[2 2 3 2 5; 2 5 6 2 5; 9 8 9 2 5];
SH=shadowHist(y,'ShadowType',{'/','\','.','_','+'});
SH=SH.draw();
SH=SH.legend({'AAAAAAA','BBBBBBB','CCCCCCC','DDDDDDD','EEEEEEE'},'FontName','Cambria','FontSize',11);
% 修饰阴影变成红色并加粗
shadowHdl=findobj('Tag','barShadow');
for i=1:length(shadowHdl)
if isa(shadowHdl(i),'matlab.graphics.chart.primitive.Line')
shadowHdl(i).Color=[.8,.6,.6];
shadowHdl(i).LineWidth=1;
else
shadowHdl(i).MarkerFaceColor=[.8,.6,.6];
shadowHdl(i).SizeData=5;
end
end
% 修饰框变为蓝色并加粗
boxHdl=findobj('Tag','barBox');
for i=1:length(boxHdl)
boxHdl(i).EdgeColor=[.3,.3,.8];
boxHdl(i).LineWidth=2;
end
% 图例框加粗并变成绿色
lgdBox=findobj('Tag','lgdBox');
lgdBox.LineWidth=1.3;
lgdBox.EdgeColor=[.1,.3,.1];
lgdBox.FaceColor=[173,189,163]./255;
光看上面代码大佬们应该就已经懂了咋用,如果比较小白,可以直接使用MATLAB自带的属性修饰器:
点击:查看->属性修饰器
点击选中对象即可立即修饰颜色、粗细等各种格式:
classdef shadowHist
% @author : slandarer
% gzh : slandarer随笔
% 使用示例:
% =========================================================================
% y=[2 2 3 2 5; 2 5 6 2 5; 9 8 9 2 5];
%
% SH=shadowHist(y,'ShadowType',{'/','\','.','x','|'});
% SH=SH.draw();
properties
ax % 绘图坐标区域
YData % 数值矩阵
shadowTypeList={'\','/','_','|','+','x','.','w','k','g'}
shadowType % 阴影类型
otherProp % 其他初始属性
oriBarHdl % 原始图形句柄
newBarHdl
pshapeHdl % polyshape图形句柄
groupNum % 组数
classNum % 类数
YEndMat % 末端y值
maxY % 最大Y值
minY=0 % 最小Y值
diffY % Y值之差
BarW % 宽度
YSep1 % linspace(obj.minY,obj.maxY+.02.*obj.diffY,obj.lineNum)
YSep2
XMean % 每组柱状图每个柱子的中心位置
lineNum=90 % 阴影基础线数量
XYRate
SHLegend
oriLegend
end
methods
function obj=shadowHist(varargin)
% 基础属性设置
if isa(varargin{1},'matlab.graphics.axis.Axes')
obj.ax=varargin{1};varargin(1)=[];
else
obj.ax=gca;
end
hold(obj.ax,'on');
obj.YData=varargin{1};varargin(1)=[];
if any(strcmpi('shadowType',varargin))
tind=find(strcmpi('shadowType',varargin));
obj.shadowType=varargin{tind+1};
varargin([tind,tind+1])=[];
else
obj.shadowType=obj.shadowTypeList;
end
obj.otherProp=varargin;
help shadowHist
end
function obj=draw(obj)
% 基础绘图
obj.oriBarHdl=bar(obj.ax,obj.YData,obj.otherProp{:},'Tag','barBox');
obj.XYRate=diff(obj.ax.YLim)./diff(obj.ax.XLim);
% 更多属性获取
obj.YEndMat=zeros([length(obj.oriBarHdl),length(obj.oriBarHdl(1).XData)]);
for i=1:length(obj.oriBarHdl)
obj.YEndMat(i,:)=obj.oriBarHdl(i).YEndPoints;
end
obj.maxY=max(obj.YEndMat,[],[1,2]);
obj.minY=min(0,min(obj.YEndMat,[],[1,2]));
obj.diffY=obj.maxY-obj.minY;
obj.classNum=length(obj.oriBarHdl);
obj.groupNum=length(obj.oriBarHdl(1).XData);
% 计算柱状图宽度和位置
% obj.XMean=linspace(-obj.classNum+1,obj.classNum-1,obj.classNum)./(3+2*obj.classNum);
for i=1:obj.classNum
obj.XMean(i)=obj.oriBarHdl(i).XEndPoints(1)-1;
end
tXMean=[obj.XMean,1];obj.BarW=(tXMean(2)-tXMean(1))./2.*obj.oriBarHdl(1).BarWidth;
if strcmp(obj.oriBarHdl(1).BarLayout,'stacked')
obj.BarW=1./2.*obj.oriBarHdl(1).BarWidth;
end
YY1=linspace(obj.minY,obj.maxY+.02.*obj.diffY,obj.lineNum)';
YY2=linspace(obj.minY-.02.*obj.diffY,obj.maxY,obj.lineNum)';
obj.YSep1=YY1(1)-YY2(2);obj.YSep2=YY1(2)-YY1(1);
% 循环绘制阴影
for i=1:obj.classNum
obj.oriBarHdl(i).FaceColor='none';
obj.oriBarHdl(i).LineWidth=.8;
if strcmp(obj.oriBarHdl(1).BarLayout,'stacked')
obj.oriBarHdl(i).LineWidth=.8;
end
tType=mod(i-1,length(obj.shadowType))+1;
switch obj.shadowType{tType}
case 'w',obj.oriBarHdl(i).FaceColor=[1,1,1];
case 'k',obj.oriBarHdl(i).FaceColor=[0,0,0];
case 'g',obj.oriBarHdl(i).FaceColor=[.5,.5,.5];
end
for j=1:obj.groupNum
tX=[-1,1,1,-1].*obj.BarW+obj.XMean(i)+j;
tY=[obj.oriBarHdl(i).YEndPoints(j)-obj.oriBarHdl(i).YData(j),...
obj.oriBarHdl(i).YEndPoints(j)-obj.oriBarHdl(i).YData(j),...
obj.oriBarHdl(i).YEndPoints(j),...
obj.oriBarHdl(i).YEndPoints(j)];
tPolyPhape=polyshape(tX,tY);
switch obj.shadowType{tType}
case '\'
XX1=-1.2.*ones([obj.lineNum,1]).*obj.BarW+obj.XMean(i)+j;
XX2=1.2.*ones([obj.lineNum,1]).*obj.BarW+obj.XMean(i)+j;
YY1=linspace(obj.minY,obj.maxY+.02.*obj.diffY,obj.lineNum)';
YY2=linspace(obj.minY-.02.*obj.diffY,obj.maxY,obj.lineNum)';
tXX=zeros([3,obj.lineNum]);tYY=zeros([3,obj.lineNum]);
for k=1:obj.lineNum
[in,~]=intersect(tPolyPhape,[XX1(k),YY1(k);XX2(k),YY2(k)]);
if ~isempty(in)
tXX(:,k)=[in(1,1);in(end,1);nan];
tYY(:,k)=[in(1,2);in(end,2);nan];
else
tXX(:,k)=[nan;nan;nan];
tYY(:,k)=[nan;nan;nan];
end
end
plot(tXX(:),tYY(:),'Color',[0,0,0],'LineWidth',.5,'Tag','barShadow')
case '/'
XX1=-1.2.*ones([obj.lineNum,1]).*obj.BarW+obj.XMean(i)+j;
XX2=1.2.*ones([obj.lineNum,1]).*obj.BarW+obj.XMean(i)+j;
YY1=linspace(obj.minY-.02.*obj.diffY,obj.maxY,obj.lineNum)';
YY2=linspace(obj.minY,obj.maxY+.02.*obj.diffY,obj.lineNum)';
tXX=zeros([3,obj.lineNum]);tYY=zeros([3,obj.lineNum]);
for k=1:obj.lineNum
[in,~]=intersect(tPolyPhape,[XX1(k),YY1(k);XX2(k),YY2(k)]);
if ~isempty(in)
tXX(:,k)=[in(1,1);in(end,1);nan];
tYY(:,k)=[in(1,2);in(end,2);nan];
else
tXX(:,k)=[nan;nan;nan];
tYY(:,k)=[nan;nan;nan];
end
end
plot(tXX(:),tYY(:),'Color',[0,0,0],'LineWidth',.5,'Tag','barShadow')
case '_'
tXX=[tX(1),tX(2),nan];
tYY=linspace(obj.minY-.02.*obj.diffY,obj.maxY+.02.*obj.diffY,obj.lineNum)';
tYY(tYY>=max(tY))=[];tYY(tYY=max(tY))=[];tYY(tYY=max(tY))=[];tYY(tYY
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?