WinForm使用原生gdi+绘制自定义曲线图、折线图
折线图我们可以用chart控件,但是有时候需要一些自定义元素,比如曲线图放大、曲线图缩小、曲线图拖放等,因此自定义更加灵活
但是自定义有自己的缺点,就是功能有限。
1.原理
winform的自定义控件,在onpaint事件里,通过Graphics对象,将x轴、y轴,曲线绘制出来。
为了每次能够拖拽放大缩小,在每次拖放过程中,加入计算,即计算范围和刻度线位置。
2.计算
比如x的范围是 222到999,为了使轴线的刻度为整数,我们将范围扩大到200到1000。为了取得正确的范围,我们需要进行以下计算。
- 当222的时候,对222取对数,log10(222)=2.34。
- 2.34取整数部分2,再用10求指数,得10^2=100。
- 2.34取小于它的最大整数,Math.Floor(2.34)=2。
- 2乘以100=200。
同理999也一样,只不过Math.Floor改成Math.Ceiling,取大于它的最小整数
代码片段如下
/// <summary> /// 获取比value大的或者小的整数值 /// </summary> /// <param name="value">要处理的值</param> /// <param name="isBiggerThanValue">是否比value大</param> /// <returns></returns> private decimal GetProperValue(decimal value, bool isBiggerThanValue) { var positive = value > 0 ? 1 : -1; //负值转换为正,正值为本身 value = value * positive; var temp = value; int tenPowPart = 0; if (temp > 1) { while (temp >= 10) { tenPowPart++; temp = value * (decimal)Math.Pow(0.1, tenPowPart); } if (isBiggerThanValue) { temp = positive == 1 ? Math.Ceiling(temp) : Math.Floor(temp); } else { temp = positive == 1 ? Math.Floor(temp) : Math.Ceiling(temp); } var proper = positive * temp * (decimal)Math.Pow(10, tenPowPart); return proper; } else { while (temp < 1m && temp > 0) { tenPowPart++; temp = value * (decimal)Math.Pow(10, tenPowPart); } if (isBiggerThanValue) { temp = positive == 1 ? Math.Ceiling(temp) : Math.Floor(temp); } else { temp = positive == 1 ? Math.Floor(temp) : Math.Ceiling(temp); } var proper = positive * temp * (decimal)Math.Pow(0.1, tenPowPart); return proper; } }
其他计算类似
3.效果图源码
源码:
https://files.cnblogs.com/files/lizhijian/20201127Winform%E7%BB%98%E5%88%B6%E6%9B%B2%E7%BA%BF%E5%9B%BE.zip
修改版:
https://files.cnblogs.com/files/congqiandehoulai/20201127Winform%E7%BB%98%E5%88%B6%E6%9B%B2%E7%BA%BF%E5%9B%BE.rar