一、实现功能
1、显示面板绘制。
2、拖动面板,X轴、Y轴都可以拖动。
3、显示面板缩放,放大或者缩小。
4、鼠标在面板中对应的XY轴数值。
5、自动生成的数据数组,曲线显示。
6、鼠标是否在曲线上检测。
二、界面
拖动面板
鼠标在曲线上识别
三、部分功能代码实现
1、图形面板
/// <summary>
/// 生成坐标系图片面板
/// </summary>
/// <returns></returns>
public Bitmap DrawImage()
{
ImageBoardInit();
return bitMap;
}
/// <summary>
/// 创建绘图面板-显示坐标系
/// </summary>
private void ImageBoardInit()
{
//1、绘制X、Y坐标轴
if ((int)height != 0 && (int)width != 0) //做这个判断是因为在最小化的情况下width=0。
{
bitMap = new Bitmap((int)width, (int)height); //根据给定的高度和宽度创建一个位图图像
}
graphics = Graphics.FromImage(bitMap); //从指定的 objBitmap 对象创建 objGraphics 对象 (即在objBitmap对象中画图)
//根据给定颜色(LightGray)填充图像的矩形区域 (背景)
graphics.DrawRectangle(new Pen(boardColor, 1), 0, 0, width - 1, height - 1); //画边框
graphics.FillRectangle(new SolidBrush(backColor), 1, 1, width - 2, height - 2); //填充边框
//画X轴,注意图像的原始X轴和Y轴计算是以左上角为原点,向右和向下计算的
xAxisPoint1.X = xSpace + xSliceBegin;
xAxisPoint1.Y = (height / 2) + ySliceBegin; //
xAxisPoint2.X = width;
xAxisPoint2.Y = xAxisPoint1.Y;
graphics.DrawLine(new Pen(new SolidBrush(axisColor), 2), xAxisPoint1, xAxisPoint2);
//画Y轴
yAxisPoint1.X = xSpace + xSliceBegin;
yAxisPoint1.Y = height ;
yAxisPoint2.X = xSpace + xSliceBegin;
yAxisPoint2.Y = 0 ;
graphics.DrawLine(new Pen(new SolidBrush(axisColor), 2), yAxisPoint1, yAxisPoint2);
//2、面板标题
//graphics.DrawString("曲线编辑器", new Font("宋体", fontSize), new SolidBrush(Color.Blue), new PointF(width / 2, ySpace / 2));
//3、画X轴上刻度、刻度说明
xSlice = (width - xSpace ) / xSliceCount;
ySlice = (height / 2) / (ySliceCount / 2);
int tempCountX1 = (int)(- xSliceBegin / xSlice);
int tempCountY1 = (int)Math.Abs((ySliceBegin / ySlice));
tempCountX = tempCountX1 + xSliceCount;
tempCountY = tempCountY1 + ySliceCount/2;
//画网格虚线
Pen penDashed = new Pen(new SolidBrush(Color.Black));
penDashed.DashStyle = DashStyle.Dash;
for (int i = 1; i < tempCountX + 1; i++)
{
//X轴刻度虚线
graphics.DrawLine(penDashed, new PointF(i * xSlice + xSpace + xSliceBegin, 0 ), new PointF(i * xSlice + xSpace + xSliceBegin, height));
//X轴刻度值标识文字
string xStr = (i * xSliceValue).ToString();
int nStrLength = xStr.Length;
graphics.DrawString(xStr, new Font("宋体", fontSize), new SolidBrush(Color.Black), new PointF(i * xSlice + xSpace - fontSize * nStrLength + xSliceBegin, height / 2 + fontSize + ySliceBegin));
}
//Y轴虚线、刻度文字-正半轴
for (int i = 0; i < tempCountY + 1; i++)
{
graphics.DrawLine(penDashed, new PointF(xSpace + xSliceBegin, height / 2 - i * ySlice + ySliceBegin), new PointF(width, height / 2 - i * ySlice + ySliceBegin));
//Y轴刻度值标识文字
string yStr = (i * ySliceValue).ToString();
int nStrLength = yStr.Length;
if(i>0)
graphics.DrawString(yStr, new Font("宋体", fontSize), new SolidBrush(Color.Black), new PointF(xSpace - fontSize * nStrLength + xSliceBegin, height / 2 - i * ySlice + ySliceBegin));
}
//Y轴虚线、刻度文字-负半轴
for (int i = 1; i < tempCountY + 1; i++)
{
graphics.DrawLine(penDashed, new PointF(xSpace + xSliceBegin, height / 2 + i * ySlice + ySliceBegin), new PointF(width, height / 2 + i * ySlice + ySliceBegin));
//Y轴刻度值标识文字
string yStr = (-i * ySliceValue).ToString();
int nStrLength = yStr.Length;
graphics.DrawString(yStr, new Font("宋体", fontSize), new SolidBrush(Color.Black), new PointF(xSpace - fontSize * nStrLength + xSliceBegin, height / 2 + i * ySlice + ySliceBegin));
}
//4、原点刻度说明
graphics.DrawString("0", new Font("宋体", fontSize + 2), new SolidBrush(Color.Black), new PointF(xSpace - fontSize * 2 + xSliceBegin, height / 2 + ySliceBegin));
}
2、数据点曲线显示
/// <summary>
/// 绘制XY轴曲线
/// </summary>
/// <param name="xDatas">X轴数据</param>
/// <param name="yDatas">Y轴数据</param>
/// <param name="splineColor">曲线颜色</param>
/// <param name="tension">曲线系数:0.0f-1.0f,默认0.5f,0.0f是直线</param>
/// <param name="isPointFill">是否标出点</param>
public void DrawXY(float[] xDatas,float[] yDatas,Color splineColor,float tension,bool isPointFill)
{
int xLength = xDatas.Length;
int yLength = yDatas.Length;
if(xLength!=yLength)
{
graphics.DrawString("X和Y数据长度不相等",new Font("宋体", fontSize + 5), new SolidBrush(Color.Blue), new Point((int)xSpace, (int)(height / 2)));
return;
}
PointF[] splinePoints = new PointF[xDatas.Length];
float xSlicePos = 0, ySlicePos = 0; //转换后的点在Image面板上像素点位置
Brush brushPoint = new SolidBrush(splineColor); //数据点画刷
for(int i=0;i<xDatas.Length;i++)
{
xSlicePos = xSliceBegin + xSpace + xDatas[i] * xSlice / xSliceValue;
ySlicePos = ySliceBegin + height / 2 - yDatas[i] * ySlice / ySliceValue;
splinePoints[i] = new PointF(xSlicePos, ySlicePos);
if (isPointFill)
{
//graphics.FillEllipse(brushPoint, xSlicePos - 4, ySlicePos - 4, 8, 8); //原点
graphics.FillRectangle(brushPoint, xSlicePos - 4, ySlicePos - 4, 8, 8); //矩形
}
}
graphics.DrawCurve(new Pen(splineColor, 2.0f), splinePoints, tension);
//graphics.Dispose();
}
3、鼠标当前所在面板位置对应的坐标系统XY值
int ex = 0, ey = 0;
int mouseToValueX = 0;
float mouseToValueY = 0; //鼠标位置当前值
float fMouseToValueX = 0;
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
ex = e.X;
ey = e.Y;
//1、显示鼠标在坐标系内X、Y对应的值
fMouseToValueX =cureDraw.MousePosToValue_X(ex);
mouseToValueX = (int)Math.Round(cureDraw.MousePosToValue_X(ex));
//mouseToValueY = (float)Math.Round(cureDraw.MousePosToValue_Y(ey));
mouseToValueY = cureDraw.MousePosToValue_Y(ey);
if (mouseToValueX<0)
{
mouseToValueX = 0;
}
if (mouseToValueX >= 0 && ex < pictureBox1.Width - 60)
{
labMousePos.Text = "X:" + mouseToValueX.ToString() + ";" + "Y:" + mouseToValueY.ToString();
labMousePos.Location = new Point(ex + 50, ey + 40);
}
if (mouseToValueX >= 0 && ex > pictureBox1.Width - 60)
{
labMousePos.Text = "X:" + mouseToValueX.ToString() + ";" + "Y:" + mouseToValueY.ToString();
labMousePos.Location = new Point(ex - 50, ey + 40);
}
}
4、鼠标是否在曲线上检测
bool isMouseOn = false;
private void timer1_Tick(object sender, EventArgs e)
{
//bool isMouseOn = cureDraw.IsMouseOnPointCheck(xDatas, yDatas, ex, ey);
//bool isMouseOn = cureDraw.IsMouseOnPointCheck(xDatasExpand, yDatasExpand, ex, ey);
float tempX = 0, tempY = 0;
int n = 0;
bool b1 = false, b2 = false;
foreach (var xData in xDatasExpand)
{
if(Math.Abs(xData-fMouseToValueX)<0.02)
{
tempX = xData;
}
}
for (int i = 0; i < xDatasExpand.Length;i++ )
{
if(xDatasExpand[i]==tempX)
{
n = i;
}
}
if (Math.Abs(yDatasExpand[n] - mouseToValueY)<2.5)
{
isMouseOn = true;
}
else
{
isMouseOn = false;
}
txtValue1.Text = xDatasExpand[n].ToString(); //Y
txtValue2.Text = fMouseToValueX.ToString();
txtValue3.Text = yDatasExpand[n].ToString(); //X
txtValue4.Text = mouseToValueY.ToString();
txtValue5.Text = n.ToString();
if (isMouseOn)
{
labMousePos.ForeColor = Color.Red;
}
else
{
labMousePos.ForeColor = Color.Black;
}
}
四、、工程下载链接
https://download.csdn.net/download/panjinliang066333/89775386