==> 学习汇总(持续更新)
==> 从零搭建后端基础设施系列(一)-- 背景介绍
有个画扇形的API,但是现在先不解释,因为不懂画饼图的原理,你也不懂怎么用。接下来就一步步带大家去计算饼图的扇形两点坐标。
直接看下图,文字解释总是太抽象。
接下来就是用Pie这个函数来画出扇形了。
其原型如下:
BOOL Pie(
LPCRECT lpRect,
POINT ptStart,
POINT ptEnd
);
lpRect: 这个就是上图中的外接矩形
ptStart: 扇形的起点
ptEnd: 扇形的终点
这里的起点终点指的是,从圆心引出的直线,相交于圆的两点,一般假设角度大的为终点。
还有一个比较重要的问题,那就是坐标原点的设置,要知道在MFC中,坐标原点是左上角开始(0,0)处,如果我们接着用这个坐标原点的话,会导致坐标的计算很复杂。所以要用SetViewportOrgEx函数设置坐标的原点。设置后,其增长方式仍然没变,往右是x增大的方向,往下是y增大的方向,相反即为负。
核心代码如下:
CPaintDC dc(this);
CRect rect;
GetClientRect(&rect);
CBrush brush(RGB(255, 255, 255));
dc.FillRect(&rect, &brush);
//设置坐标原点
SetViewportOrgEx(dc, m_COpt.x, m_COpt.y, NULL);
//设置圆的外接矩形大小
CRect pieRect(-m_Radius, -m_Radius, m_Radius, m_Radius);
dc.Ellipse(&pieRect);
POINT pt_start;
POINT pt_end;
//画饼图
double R = m_Radius;
const double PI = 3.1415926;
double sum = 0;
for (int i = 0; i < m_itemNums; i++)
sum += m_percentage[i];
//验证占比加起来等不等于1
if (sum == 1)
{
//第一个扇形的坐标
int angle = m_percentage[0] * 360; //计算占的角度
POINT pt_s_e;
pt_start = { (int)R,0 };
pt_s_e = pt_start;
pt_end = { int(R*cos(angle * PI / 180)),int(-R*sin(angle * PI / 180)) };
dc.SelectObject(CreateSolidBrush(m_color[0])); //上颜色
dc.Pie(&pieRect, pt_start, pt_end);
for (int i = 1; i < m_itemNums; i++)
{
pt_start = pt_end;
angle += m_percentage[i] * 360;
pt_end = { int(R*cos(angle * PI / 180)),int(-R*sin(angle * PI / 180)) };
dc.SelectObject(CreateSolidBrush(m_color[i])); //上颜色
if(i == m_itemNums - 1)
dc.Pie(&pieRect, pt_start, pt_s_e);
else
dc.Pie(&pieRect, pt_start, pt_end);
}
//画小矩形
CRect expRect;
int l = 0, t = 0;
for (int i = 0; i < m_itemNums; i++)
{
l = m_Radius + 50;
t = -2*m_Radius + m_expH*i;
expRect = {l,t + 10,l + m_expW,t + m_expH };
dc.SelectObject(CreateSolidBrush(m_color[i])); //上颜色
dc.Rectangle(&expRect);
dc.TextOut(l + m_expW + 10, t + m_expH / 3, m_itemName[i]);
}
//显示百分比
CString s;
int strLen = m_itemName[0].GetLength();
for (int i = 0; i < m_itemNums; i++)
{
l = -2*m_Radius - strLen*10;
t = -2 * m_Radius + m_expH*i;
s.Format(TEXT("%s -- %0.2f%s"), m_itemName[i],m_percentage[i] * 100,TEXT("%"));
dc.TextOut(l, t + m_expH / 3, s);
}
}
我把画饼图的方法,封装成一个通用的类,以添加item的方式,添加扇形。
使用示例如下:
PieChart piechart;
piechart.SetCoordinateOrigin({ 300,200 }); //设置坐标原点
piechart.SetRadius(100); //设置半径
piechart.SetExplainRect(50,30); //设置小矩形大小
piechart.AddItem("苹果", RGB(255, 0, 0), 0.4);
piechart.AddItem("雪梨", RGB(0, 255, 0), 0.1);
piechart.AddItem("香蕉", RGB(0, 0, 255), 0.2);
piechart.AddItem("木瓜", RGB(0, 255, 255), 0.3);
piechart.DoModal();
结果如图:
饼图类下载(github下载)
饼图类下载(这是CSDN下载,需要1积分)
注:因为我是在VS2015编译的,只能保证向下兼容到2013,其它版本可能有不确定错误。或者直接把有用代码复制粘贴,这样就能保证能兼容所有VS,VC就需要改动多一点才能正常运行。