C#时间轴曲线图形编辑器开发1-基本功能

这篇具有很好参考价值的文章主要介绍了C#时间轴曲线图形编辑器开发1-基本功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、前言

1、简介

2、开发过程

3、工程下载链接

二、基本功能实现

1、绘图面板创建

(1)界面布置

(2)显示面板代码

(3) 面板水平方向、竖直方向移动功能实现

(4)面板放大、缩小、恢复正常显示功能实现

(5)鼠标当前位置坐标值和界面显示

(6)面板实现效果操作演示

 2、数据曲线在面板上显示

(1)曲线数据变量定义

(2)曲线数据生成按钮事件函数

(3)曲线是否显示复选框事件函数

(4)面板上绘制曲线图形

(5)添加曲线清除按钮

(6)曲线显示操作演示

(7)代码工程下载链接

 3、鼠标在曲线上识别

(1)添加变量

(2)读取文本文件数据

(3)显示读取的两列数据曲线

(4)鼠标在两列数据曲线上识别

(5)代码下载链接

4、时间轴曲线当前所在位置指示线

 (1)添加全局变量

 (2)鼠标按键按下检测

(3)在DrawCure()中画竖直方向的指示线

(4)代码下载链接

5、鼠标拖动关键点

 (1)添加全局变量

(2) 添加几个测试的关键帧数据

(3)绘制关键帧和数据曲线

 (4)关键帧数据编辑

 (5)代码下载链接


一、前言

1、简介

通过制作简易的该曲线图形编辑器Demo,实现类似于Maya软件中的动画曲线编辑的功能。在指定的时间轴上插入关键帧,设置拖动该关键点,来编辑曲线数据。编辑好的数据导出保存在TXT文本中,同时曲线编辑器也可以读取之前导出的TXT文本数据再继续进行编辑。

C#时间轴曲线图形编辑器开发1-基本功能,编辑器

 操作演示

C#时间轴曲线图形编辑器开发1-基本功能,编辑器

 自制曲线编辑器Demo

C#时间轴曲线图形编辑器开发1-基本功能,编辑器

 Maya软件动画编辑

2、开发过程

实现曲线编辑的功能,大致分五个过程,分包为

(1)曲线绘图面板创建、显示数据曲线

(2)鼠标经过数据曲线上识别到该曲线

(3)当前时间轴位置指示线创建

(4)鼠标拖动已设置的关键帧、改变曲线

(5)任意位置添加关键帧、对关键帧数据插值得到曲线、曲线数据导出和导入

3、工程下载链接

基本功能,打包下载链接

https://download.csdn.net/download/panjinliang066333/88112693

C#时间轴曲线图形编辑器开发1-基本功能,编辑器

 全部功能测试代码

 https://download.csdn.net/download/panjinliang066333/88103699

C#时间轴曲线图形编辑器开发1-基本功能,编辑器

二、基本功能实现

1、绘图面板创建

(1)界面布置

创建C# Winform工程。

①添加pictureBox1图形控件作为曲线图形显示面板,添加hHScrollBarX、VScrollBarY控件作为显示面板水平方向、竖直方向移动。

②添加3个Button按钮,用作图形面板放大、缩小、和恢复正常。

③添加绘制曲线的按钮、添加复选框用于选择是否显示曲线

④添加Label控件,用于显示当前鼠标所在曲线图形面板中的坐标位置。

C#时间轴曲线图形编辑器开发1-基本功能,编辑器

(2)显示面板代码

①、窗口上添加Form1_Load,

        private void Form1_Load(object sender, EventArgs e)
        {
            if (xLineDatas.Length > dataF.Length)
            {
                hScrollBarX.Maximum = (int)xLineDatas.Max();
            }
            else
            {
                hScrollBarX.Maximum = dataF.Length;
            }
            isSpline1Show = !checkSpline1Show.Checked;

            timer1.Start();
            cureDraw = new SplineEdit(pictureBox1.Height, pictureBox1.Width);
            DrawCure();
        }

②、添加定时器,创建定时器事件函数

         private void timer1_Tick(object sender, EventArgs e)
        {
            DrawCure();
        }

③、DrawCure()封装的代码如下

        private void DrawCure()
        {
            if (pictureBox1.Height > 0 && pictureBox1.Width > 0)
            {
                cureDraw.Height = pictureBox1.Height;
                cureDraw.Width = pictureBox1.Width;
            }

            pictureBox1.Image = cureDraw.DrawImage();
        }

cureDraw为自定义封装的类SplineEdit实例对象。

④、DrawImage(),创建显示坐标系面板

        /// <summary>
        /// 生成坐标系图片面板
        /// </summary>
        /// <returns></returns>
        public Bitmap DrawImage()
        {
            ImageBoardInit();   //绘图面板
            return bitMap;
        }      

ImageBoardInit():绘制面板

        /// <summary>
        /// 创建绘图面板-显示坐标系
        /// </summary>
        private void ImageBoardInit()
        {
            int tempCountX = 0;
            int tempCountY = 0;  

            //1、绘制X、Y坐标轴

            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));
        }

⑤、制作出的图形面板显示如下

C#时间轴曲线图形编辑器开发1-基本功能,编辑器

(3) 面板水平方向、竖直方向移动功能实现

分别添加hScrollBarX_ValueChanged、vScrollBarY_ValueChanged控件事件函数

hScrollBarX_ValueChanged:

        private void hScrollBarX_ValueChanged(object sender, EventArgs e)
        {
            cureDraw.XSliceBegin = -hScrollBarX.Value * cureDraw.XSlice / cureDraw.XSliceValue;
            Invalidate();   //更新界面
        }

vScrollBarY_ValueChanged:

        private void vScrollBarY_ValueChanged(object sender, EventArgs e)
        {
            cureDraw.YSliceBegin = vScrollBarY.Value * cureDraw.YSlice / cureDraw.YSliceValue;
            Invalidate();   //更新界面
        }

cureDraw.XSliceBegin:X轴数值0点在屏幕起始像素位置

cureDraw.YSliceBegin:Y轴数值0点在屏幕起始像素位置

(4)面板放大、缩小、恢复正常显示功能实现

分别添加按钮事件函数btnScaleBigger_Click、btnScaleSmaller_Click、btnReset_Click

btnScaleBigger_Click:

        private void btnScaleBigger_Click(object sender, EventArgs e)
        {
            cureDraw.XSliceCount -= 1;
            cureDraw.YSliceCount -= 1;
            Invalidate();   //更新界面
        }

btnScaleSmaller_Click:

        private void btnScaleSmaller_Click(object sender, EventArgs e)
        {
            cureDraw.XSliceCount += 1;
            cureDraw.YSliceCount += 1;
            Invalidate();   //更新界面
        }

btnReset_Click:

        private void btnReset_Click(object sender, EventArgs e)
        {
            cureDraw.XSliceCount = 15;
            cureDraw.YSliceCount = 10;
            hScrollBarX.Value = 0;
            vScrollBarY.Value = 0;
        }

(5)鼠标当前位置坐标值和界面显示

①控件pictureBox1上添加pictureBox1_MouseMove事件函数

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            int ex = 0, ey = 0;         //鼠标的坐标值
            int mouseToValueX = 0;
            float mouseToValueY = 0;    //鼠标位置对应的数值
            float fMouseToValueX = 0;

            ex = e.X;                   //鼠标在pictureBox1中X轴坐标值
            ey = e.Y;                   //鼠标在pictureBox1中Y轴坐标值
            fMouseToValueX = cureDraw.MousePosToValue_X(ex);
            mouseToValueX = (int)Math.Round(cureDraw.MousePosToValue_X(ex));
            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);
            }
        }

②cureDraw.MousePosToValue_X:鼠标在pictureBox1面板上X轴的像素值转换为坐标系X轴的值

        /// <summary>
        /// 鼠标画板上横向位置转换成坐标x轴数值
        /// </summary>
        /// <param name="ex"></param>
        /// <returns></returns>
        public float MousePosToValue_X(float ex)
        {
            return (ex - xSpace - xSliceBegin) * xSliceValue / xSlice; ;
        }

③cureDraw.MousePosToValue_Y:鼠标在pictureBox1面板上Y轴的像素值转换为坐标系Y轴的值

        /// <summary>
        /// 鼠标画板上竖向位置转换成坐标y轴数值
        /// </summary>
        /// <param name="ey"></param>
        /// <returns></returns>
        public float MousePosToValue_Y(float ey)
        {
            return (ySliceBegin + height / 2 - ey) * ySliceValue / ySlice;
        }

(6)面板实现效果操作演示

C#时间轴曲线图形编辑器开发1-基本功能,编辑器

 2、数据曲线在面板上显示

         曲线1为显示Sin曲线、曲线2为显示生成的随机数曲线。

         曲线1显示函数,需要分别提供X轴、Y轴的坐标位置数组,且两个数组长度必须相等


public void DrawXY(float[] xDatas, float[] yDatas, Color splineColor, float tension, bool isPointFill)

 曲线2显示函数,只需要曲线Y轴上位置数组。(数据的长度即为X轴数据)


public void DrawSpline(float[] yDatas, Color splineColor, float tension, bool isPointFill)

(1)曲线数据变量定义

        //曲线1
        bool isSpline1Show = false;
        float[] xLineDatas = new float[501];            //保存绘制的点 x、y轴位置
        float[] yLineDatas = new float[501];
        Color spline1Color = Color.Green;               //曲线1颜色  
        float tensionSpline1 = 0.5f;                    //曲线1粗细
        //曲线2
        bool isSpline2Show = false;
        float[] dataF = new float[10000];
        Color spline2Color = Color.Red;                 //曲线2颜色  
        float tensionSpline2 = 0.5f;                    //曲线2粗细
        Random rd = new Random();

(2)曲线数据生成按钮事件函数

分别添加曲线1按钮、曲线2按钮事件函数btnDrawSpline1_Click、btnDrawSpline2_Click

btnDrawSpline1_Click:

        private void btnDrawSpline1_Click(object sender, EventArgs e)
        {
            //isLineSplineShow = false;
            isSpline1Show = checkSpline1Show.Checked;

            //1、生成sin曲线,保存x、y坐标位置
            for (int i = 0; i < xLineDatas.Length; i++)
            {
                xLineDatas[i] = i;
                yLineDatas[i] = 32 * (float)Math.Sin(36 * i * Math.PI / 180);
            }

            Invalidate();   //更新界面
        }

btnDrawSpline2_Click:

        private void btnDrawSpline2_Click(object sender, EventArgs e)
        {            
            for (long i = 1; i < dataF.Length; i++)
            {
                dataF[i] = (float)rd.Next(-20, 20);
            }
            isSpline2Show = true;
        }

(3)曲线是否显示复选框事件函数

分别添加曲线1、曲线2显示复选框事件函数:heckSpline1Show_CheckedChanged、checkSpline2Show_CheckedChanged

heckSpline1Show_CheckedChanged

        private void checkSpline1Show_CheckedChanged(object sender, EventArgs e)
        {
            isSpline1Show = checkSpline1Show.Checked;
        }

checkSpline2Show_CheckedChanged

        private void checkSpline2Show_CheckedChanged(object sender, EventArgs e)
        {
            isSpline2Show = checkSpline2Show.Checked;
        }

(4)面板上绘制曲线图形

修改前面的DrawCure()函数

         private void DrawCure()
        {

            if (pictureBox1.Height > 0 && pictureBox1.Width > 0)        //若窗口最小化时候,则Height、Width都为0。DrawImage()创建图像会出错
            {
                cureDraw.Height = pictureBox1.Height;
                cureDraw.Width = pictureBox1.Width;
            }
            pictureBox1.Image = cureDraw.DrawImage();

            //曲线1显示
            if (isSpline1Show == true)
            {
                cureDraw.DrawXY(xLineDatas, yLineDatas, spline1Color, tensionSpline1, false);
            }

            //曲线2显示
            if (isSpline2Show == true)
            {
                cureDraw.DrawSpline(dataF, spline2Color, tensionSpline2, false);
            }           
        }

(5)添加曲线清除按钮

用于清除曲线数据和不再显示曲线

        private void btnDataClear_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < xLineDatas.Length; i++)
            {
                xLineDatas[i] = 0;
                yLineDatas[i] = 0;
            }

            for (int i = 0; i < dataF.Length; i++)
            {
                dataF[i] = 0.0f;
            }
            isSpline2Show = false;
        }

(6)曲线显示操作演示

C#时间轴曲线图形编辑器开发1-基本功能,编辑器

(7)代码工程下载链接

该链接为个人使用。

链接:https://pan.baidu.com/s/1K6HFh56YfvwvoAH5nrdJmg 
提取码:vfym 
--来自百度网盘超级会员V4的分享

 3、鼠标在曲线上识别

        读取TXT文本文件中的两列数据,将两列数据以曲线显示出来,当鼠标移动经过曲线时显示当前坐标的Label控件字体颜色变成当前识别的曲线颜色。

C#时间轴曲线图形编辑器开发1-基本功能,编辑器

 曲线识别效果

(1)添加变量

        //曲线-导入数据
        bool isSplineAxis = false;
        float[] axis1Data, axis2Data;
        Color Axis1Color = Color.Red;                   //Axis1曲线颜色
        Color Axis2Color = Color.Blue;                  //Axis2曲线颜色
        bool isMouseOnAxis1, isMouseOnAxis2;            //检测鼠标是否在曲线上

(2)读取文本文件数据

     文本文件数据,附在下载链接中。

C#时间轴曲线图形编辑器开发1-基本功能,编辑器

如效果图所示添加按钮控件,导入读取文本数据。添加btnImportTxtDatas_Click事件函数

        private void btnImportTxtDatas_Click(object sender, EventArgs e)
        {
            try
            {

                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Filter = "All files(*.*)|*.*|文本文件(*.csv)|*.csv|文本文件(*.txt)|*.txt";
                if (ofd.ShowDialog() != DialogResult.OK)
                {
                    return;
                }
                int dataColumNums = 0;              //动作文件列表数
                int dataLineNums;                   //动作行数
                double[,] axisDataArrayRead;                


                string[] lines = File.ReadAllLines(ofd.FileName, Encoding.Default).ToArray();
                dataColumNums = CharNum(lines[0], ";");
                dataLineNums = lines.Length;

                axisDataArrayRead = new double[dataColumNums, dataLineNums];
                for (int i = 0; i < lines.Length; i++)
                {
                    string[] seg = lines[i].Split(';');    //英文逗号分隔符
                    for (int j = 0; j < dataColumNums; j++)
                    {
                        axisDataArrayRead[j, i] = Convert.ToDouble(seg[j]);
                    }
                }
                //
                axis1Data = new float[dataLineNums];
                axis2Data = new float[dataLineNums];
                for(int i=0;i<dataLineNums;i++)
                {
                    axis1Data[i] = (float)axisDataArrayRead[0, i];
                    axis2Data[i] = (float)axisDataArrayRead[1, i];
                }
                isSplineAxis = true;
                hScrollBarX.Maximum = dataLineNums + 10;
            }
            catch
            {
                isSplineAxis = false;
                MessageBox.Show("文件解析异常", "提示");
            }
        }

(3)显示读取的两列数据曲线

   修改DrawCure(),添加代码

        private void DrawCure()
        {
            if (pictureBox1.Height > 0 && pictureBox1.Width > 0)        //若窗口最小化时候,则Height、Width都为0。DrawImage()创建图像会出错
            {
                cureDraw.Height = pictureBox1.Height;
                cureDraw.Width = pictureBox1.Width;
            }            
            pictureBox1.Image = cureDraw.DrawImage();

            //曲线1显示
            if (isSpline1Show == true)
            {
                cureDraw.DrawXY(xLineDatas, yLineDatas, spline1Color, tensionSpline1, false);
            }
            //曲线2显示
            if (isSpline2Show == true && spline2DataState == 1)
            {
                cureDraw.DrawSpline(dataF, spline2Color, tensionSpline2, false);                
            }

            //读取的文本文件两列数据显示
            if(isSplineAxis)
            {
                if (checkAxis1.Checked)
                {
                    cureDraw.DrawSpline(axis1Data, Axis1Color, 0.5f, false);
                }
                if (checkAxis2.Checked)
                {
                    cureDraw.DrawSpline(axis2Data, Axis2Color, 0.5f, false);
                }                
                
            }

        }

(4)鼠标在两列数据曲线上识别

修改timer1_Tick()函数

        private void timer1_Tick(object sender, EventArgs e)
        {
            DrawCure();

            //检测鼠标是否在曲线上
            if(isSplineAxis)
            {
                int nIndex = 0;

                //第一列数据曲线识别
                if (checkAxis1.Checked)
                {
                    nIndex = currentValue_X;
                    if (nIndex >= axis1Data.Length)
                    {
                        nIndex = axis1Data.Length-1;
                    }
                    float selectValue_Y_Axis1 = axis1Data[nIndex];
                    if (Math.Abs(selectValue_Y_Axis1 - currentValue_Y) < cureDraw.YSliceValue/8)
                    {
                        isMouseOnAxis1 = true;
                        labMousePos.ForeColor = Axis1Color;
                    }
                    else
                    {
                        isMouseOnAxis1 = false;
                        //labMousePos.ForeColor = Color.Black;
                    }
                }

                //第二列数据曲线识别
                if (checkAxis2.Checked)
                {
                    nIndex = currentValue_X;
                    if (nIndex >= axis1Data.Length)
                    {
                        nIndex = axis1Data.Length-1;
                    }
                    float selectValue_Y_Axis2 = axis2Data[nIndex];
                    if (Math.Abs(selectValue_Y_Axis2 - currentValue_Y) < cureDraw.YSliceValue / 8)
                    {
                        isMouseOnAxis2 = true;
                        labMousePos.ForeColor = Axis2Color;
                    }
                    else
                    {
                        isMouseOnAxis2 = false;
                        //labMousePos.ForeColor = Color.Black;
                    }
                }


                if(isMouseOnAxis1==false && isMouseOnAxis2==false)
                {
                    labMousePos.ForeColor = Color.Black;
                }

            }

        }

(5)代码下载链接

该链接为个人使用。

链接:https://pan.baidu.com/s/1FQNVWU-PLIgaS3KmQz_BGw 
提取码:dtcj 
--来自百度网盘超级会员V4的分享

4、时间轴曲线当前所在位置指示线

     创建一条竖直方向的线,用来指示当前鼠标点击所在的X轴位置。该线的作用是在编辑数据和运行数据的时候可以很方便的看出当前所运行到的时间点。

     指示线效果如下所示

C#时间轴曲线图形编辑器开发1-基本功能,编辑器

 (1)添加全局变量

        //鼠标当前在画图面板上的像素坐标,对应的坐标轴数值
        int currentValue_X;
        float currentValue_Y;
        int last_CurrentValueX = 0;

        bool isLeftButtonDowm = false, isMiddleButtonDown = false, isRightButtonDown = false;

 (2)鼠标按键按下检测

控件pictureBox1添加pictureBox1_MouseDown、pictureBox1_MouseUp事件函数,用来检测鼠标按键按下和抬起。

pictureBox1_MouseDown

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                isLeftButtonDowm = true;
            }
            if (e.Button == MouseButtons.Middle)
            {
                isMiddleButtonDown = true;
            }
            if (e.Button == MouseButtons.Right)
            {
                isRightButtonDown = true;
            }
        }

pictureBox1_MouseUp

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                isLeftButtonDowm = false;
            }
            if (e.Button == MouseButtons.Middle)
            {
                isMiddleButtonDown = false;
            }
            if (e.Button == MouseButtons.Right)
            {
                isRightButtonDown = false;
            }
        }

(3)在DrawCure()中画竖直方向的指示线

            //时间轴位置指示线
            cureDraw.DrawCurrentLine(last_CurrentValueX);
            if (isLeftButtonDowm)
            {
                last_CurrentValueX = currentValue_X;
            }

 DrawCurrentLine()函数如下封装

        /// <summary>
        /// 绘制当前鼠标所在X轴位置的数值,指示直线
        /// </summary>
        /// <param name="CurrentValue_X"></param>
        public void DrawCurrentLine(int CurrentValue_X)
        {

            Brush currentB = new SolidBrush(Color.Red);        //
            float ex = ValueToMousePoint_ex(CurrentValue_X);
            graphics.DrawLine(new Pen(currentB), ex, 0, ex, height);

        }

(4)代码下载链接

该链接为个人使用。

链接:https://pan.baidu.com/s/13c0C1dTqTgW-5G3uYWekOA 
提取码:u6n0 
--来自百度网盘超级会员V4的分享

5、鼠标拖动关键点

鼠标选中关键帧数据点,滑动鼠标实现对关键帧数据点的拖动。

C#时间轴曲线图形编辑器开发1-基本功能,编辑器

 (1)添加全局变量

需要拖拽的点叫关键帧点,每个关键帧点包括两个数据:X轴中位置、Y轴中位置。创建字典集合keyListDatas 来保存关键帧数据。

        //曲线编辑
        Dictionary<int, float> keyListDatas = new Dictionary<int, float>();
        Color editSplineColor = Color.Blue;                  //曲线颜色
        bool isMouseOnKeyPoint = false;     //鼠标是否在关键点上检测
        bool isKeyEditDataMoveCan = false;
        int dataLength = 0;
        float[] myEditDatas;                //曲线数据-绘制曲线显示
        float[] keyEditDatas_X;             //关键帧-方框点绘制-X轴数据
        float[] keyEditDatas_Y;             //关键帧-方框点绘制-X轴数据

        bool isDataEdit = false;
        int keyEditFrame = 0;

(2) 添加几个测试的关键帧数据

在Form1_Load()添加下面代码,添加关键帧数据

            //曲线编辑器数据
            dataLength = int.Parse(txtDataLength.Text);
            myEditDatas = new float[dataLength];
            //字典集合中添加4个随机数据
            keyListDatas.Add(100 + dataLength / 2, 40.0f);
            keyListDatas.Add(0, 0.0f);
            keyListDatas.Add(dataLength / 2, 10.0f);
            keyListDatas.Add(dataLength - 1, 0.0f);
            keyListDatas[dataLength / 2] = 50.0f;           //修改字典集合中的值
            KeyDataTrans();

KeyDataTrans():

        /// <summary>
        /// 关键帧数据集合转数组
        /// </summary>
        private void KeyDataTrans()
        {                       
            //关键点得数据值,对应到曲线数据上
            foreach (KeyValuePair<int, float> item in keyListDatas)
            {
                int key = item.Key;
                float fValue = item.Value;
                myEditDatas[key] = fValue;
            }

            //
            List<float> fListTemp_X = new List<float> { };
            List<float> fListTemp_Y = new List<float> { };
            foreach (KeyValuePair<int, float> item in keyListDatas)
            {
                int key = item.Key;
                float fValue = item.Value;

                fListTemp_X.Add(key);
                fListTemp_Y.Add(fValue);
            }
            keyEditDatas_X = fListTemp_X.ToArray();
            keyEditDatas_Y = fListTemp_Y.ToArray();
        }

(3)绘制关键帧和数据曲线

在DrawCure()中添加代码

            //曲线编辑器
            if (keyEditDatas_Y.Length>0)
            {
                cureDraw.DrawPoint(keyEditDatas_X, keyEditDatas_Y, editSplineColor, tensionSpline1, true);
            }
            if (myEditDatas.Length > 0)
            {
                cureDraw.DrawSpline(myEditDatas, editSplineColor, 0.5f, false);
            }

C#时间轴曲线图形编辑器开发1-基本功能,编辑器

 (4)关键帧数据编辑

在timer1_Tick()添加KeyPointEdit()

KeyPointEdit():

        private void KeyPointEdit()
        {
            //
            KeyDataTrans();

            //
            PointF[] pf=new PointF[keyEditDatas_X.Length];
            for(int i=0;i<keyEditDatas_X.Length;i++)
            {
                pf[i].X = cureDraw.ValueToMousePoint_ex((int)keyEditDatas_X[i]);
                pf[i].Y = cureDraw.ValueToMousePoint_ey(keyEditDatas_Y[i]);
            }

            //
            label7.BackColor = Color.Blue ;
            foreach (PointF pp  in pf)
            {
                //检测鼠标是否在圆点上
                GraphicsPath vGraphicsPath = new GraphicsPath();
                vGraphicsPath.AddEllipse(pp.X - 5, pp.Y - 5, 10, 10);       // 添加需要检测识别的点
                Region vRegion = new Region(vGraphicsPath);
                isMouseOnKeyPoint = vRegion.IsVisible(ex, ey);           // 判断点是否在圆中

                if (isMouseOnKeyPoint)
                {
                    Cursor.Current = Cursors.SizeNS;                    //设置鼠标为手指形
                    label7.BackColor = Color.Lime;
                    if(isLeftButtonDowm)
                    {
                        //isKeyEditDataMoveCan = true;
                    }
                    isKeyEditDataMoveCan = true;
                }
            }
            

            //
            if (isKeyEditDataMoveCan)
            {
                //
                for (int i = 0; i < keyEditDatas_X.Length; i++)
                {
                    if (Math.Abs(currentValue_X - keyEditDatas_X[i]) < 2)
                    {
                        isDataEdit = true;
                        keyEditFrame = (int)keyEditDatas_X[i];
                    }

                }

            }
            if (isLeftButtonDowm == false)
            {
                isDataEdit = false;
                isKeyEditDataMoveCan = false;
            }


            //
            if(isDataEdit)
            {
                keyListDatas[keyEditFrame] = currentValue_Y;
            }
        }

C#时间轴曲线图形编辑器开发1-基本功能,编辑器

 (5)代码下载链接

该链接为个人使用。

链接:https://pan.baidu.com/s/1HVAWpqR-68OY98KmgUlJbw 
提取码:hxvw 
--来自百度网盘超级会员V4的分享文章来源地址https://www.toymoban.com/news/detail-616460.html

到了这里,关于C#时间轴曲线图形编辑器开发1-基本功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 图形编辑器开发:是否要像 Figma 一样上 wasm

    大家好,我是前端西瓜哥。 wasm 拿来做 Web 端的图形编辑器貌似是不错的选择。 因为图形处理会有相当多无法利用到 WebGL GPU 加速的 CPU 密集的计算。比如对一条复杂贝塞尔曲线进行三角化,对多个图形进行复杂图形的布尔运算。 图形编辑器性能天花板 Figma 用了 wasm,我们也

    2024年02月15日
    浏览(37)
  • 图形编辑器开发:最基础但却复杂的选择工具

    大家好,我是前端西瓜哥。 对于一个图形设计软件,它最基础的工具是什么? 选择工具 。 但这个选择工具,却是相当的复杂。这次我来和各位,细说细说选择工具的一些弯弯道道。 我正在开发的图形设计工具的: https://github.com/F-star/suika 线上体验: https://blog.fstars.wang/ap

    2024年02月09日
    浏览(67)
  • 图形编辑器:历史记录设计

    大家好,我是前端西瓜哥。今天讲一下图形编辑器如何实现历史记录,做到撤销重做。 其实就是版本号的更替。每个版本保存一个状态。 要记录图形编辑器的历史记录,支持撤销重做功能,需要两个栈: 撤销(undo)栈和重做(redo)栈 。 每当用户进行一个操作(比如移动一

    2024年02月01日
    浏览(52)
  • 使用动画曲线编辑器打造炫酷的3D可视化ACE

    前言 在制作3D可视化看板时,除了精细的模型结构外,炫酷的动画效果也是必不可少的。无论是复杂的还是简单的动画效果,要实现100%的自然平滑都是具有挑战性的工作。这涉及到物理引擎的计算和对动画效果的数学建模分析。一般来说,只有专业的3D建模从业人员才能完成

    2024年02月03日
    浏览(48)
  • 如何将c#在线编辑器嵌入自己项目

    首先我们需要介绍一下这个在线编辑器,当前的在线编辑器支持c#的代码编译运行,并且无需后台服务,基于 WebAssembly 实现的在浏览器端去执行我们的 c# 代码,基于 Roslyn 提供的 Api 封装一套简单的编译,并且封装了 js 的支持,让嵌入的方式更简单。 最简单的嵌入方式是使用

    2024年02月03日
    浏览(44)
  • vi/vim 编辑器 --基本命令

    vi 是visual interface 的简称,是Linux中最经典的文本编辑器 vim是vi的加强版。兼容了vi的所有指令,不仅能编辑文本,而且具有shell程序编辑的功能,可以通过不同颜色的字体辨别语法的正确性,极大方便了程序的设计和编辑性。 命令模式(Command mode) 命令模式下,所敲的按键编

    2024年01月16日
    浏览(48)
  • 编辑器的新选择(基本不用配置)

    不用看网上那些教程Cline几乎不用配置。 点击设置直接选择Chinese, C++直接在选择就行了。 Cline是一个很好的编辑器,有很多懒人必备的功能。 这是一个 根本不用配置 的C++编辑器。  旁边有目录,而且配色也很好,语言标准可以自己选择。 但有一个缺点就是如果编辑时有问题

    2024年02月20日
    浏览(37)
  • 【Linux】顶级编辑器Vim的基本使用及配置

    👑作者主页:@安 度 因 🏠学习社区:StackFrame 📖专栏链接:Linux

    2024年02月03日
    浏览(35)
  • Linux:环境搭建、基本指令操作、Vim 编辑器的使用

    Linux 是一套 免费使用 和 自由传播 的类 Unix 操作系统,是一个基于 POSIX(可移植操作系统接口)和 UNIX 的 多用户 、 多任务 、 支持多线程 和 多 CPU 的操作系统; Linux 是一个操作系统, 操作系统本身也是一个软件 ; Linux 能运行主要的 UNIX 工具软件、应用程序和网络协议,

    2024年01月25日
    浏览(49)
  • ubuntu:vi 编辑器修改文件的基本操作指令

    Vi 编辑器是一个强大的命令行文本编辑器,它有着丰富的功能,但也可能对新用户来说有一些陡峭的学习曲线。下面是一些 Vi 编辑器中的基本操作指令: 1.打开文件 打开 Vi 并打开文件的命令是: 其中 filename 是你要编辑的文件名。 2.保存文件 在普通模式下按 Shift + :(冒号键

    2024年02月04日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包