绘画带有笔锋

最近一段时间调研书写带有笔锋的问题,一时间没有思路,然后在网上找啊找啊全是收费的。在网上找思路和源代码发现这块的资料少的可怜,没有办法只好自己研究了。

突然Duang的有种灵感爆发,想到最后两个点链接起来就是一个线段,可以把它均匀的分段然后设置笔宽。按照这种思路走发现可行。然后就拿起笔来画画写写了。。。。。。。

最后的实验效果是这样的(个人感觉看起来还挺不错的):

思路讲解:
1.先假设把两个点距离放大然后设置好固定的长度,设置好后平均分成多条均匀的线段并把每条线段点记录,注,我这块默认长度设置是2.5,设置的长度最好尽可能偏小。

 void Splitline(PointF point1, PointF point2, Graphics g)
        {
            double fz = 2.5;

            double lineline = Math.Sqrt(Math.Pow((point2.X - point1.X), 2) + Math.Pow((point2.Y - point1.Y), 2));//获取到线段的长度
            if (lineline > fz)
            {
                //平均分成多少份,然后把每份的点数保存
                int num = Convert.ToInt32(lineline / fz);
                List<PointF> points = new List<PointF>();
                double doublex = (point2.X - point1.X) / num;
                double doubley = (point2.Y - point1.Y) / num;
                for (int i = 0; i < num; i++)
                {
                    PointF pointF = new PointF(point1.X + (float)(i * doublex), point1.Y + (float)(i * doubley));
                    points.Add(pointF);
                }
                Console.WriteLine("总数:"+points.Count);
                //依次递减笔宽
                float widtline = 7.0f;
                float widthlinedj = widtline / points.Count;
                for (int i = 0; i < points.Count - 1; i++)
                {
                    widtline = widtline - widthlinedj;
                    Pen pen = new Pen(Color.Red, widtline);
                    g.DrawLine(pen, points[i], points[i + 1]);
                }
            }
        }

2.完成以上步骤后运行代码后会发现缓慢书写绘画笔锋出不来,突然拖动一笔会有笔锋,这个是因为move绘画笔记两个点相隔太近了导致笔锋没有出现。所以我们这块的在move方法里设置一个阈值来减少点这样绘画就能出现笔锋。注:鼠标这块我设置是10,触摸点这块设置5,如果设置太大了会导致书写轨迹略微有点偏移,所以阈值尽可能小。

     private void BezierPenForm_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Console.WriteLine(e.X+","+e.Y);

                double lineline = Math.Sqrt(Math.Pow((e.X - startpoint.X), 2) + Math.Pow((e.Y - startpoint.Y), 2));
                if (lineline >= 10)
                {
                    bezierPen.AddPoint(e.X, e.Y);
                    startpoint = new PointF(e.X, e.Y);
                   
                    bezierPen.Draw3(this.CreateGraphics());

                }

            }
        }

3.完成以上操作后书写操作就会有笔锋。注:一边绘画和一边出现笔锋这块需要在move的draw3里实现。

 public void Draw3(Graphics graphics)
        { 
if (points.Count < 1) {
                return;
            }   
            Pen pen = new Pen(Color.Red,7.0f);
            graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed; //高像素偏移质量
            graphics.CompositingQuality = CompositingQuality.HighSpeed;
            graphics.SmoothingMode = SmoothingMode.AntiAlias;
            pen.LineJoin = LineJoin.Round;
            pen.StartCap = LineCap.Round;
            pen.EndCap = LineCap.Round;
            //graphics.DrawLine(pen, points[points.Count-2].x, points[points.Count-2].y, points[points.Count-1].x, points[points.Count - 1].y);
            if (points.Count >= 3)
            {
               
                    graphics.DrawLine(pen, points[points.Count - 3].x, points[points.Count - 3].y, points[points.Count - 2].x, points[points.Count - 2].y);
                
                Splitline(new PointF(points[points.Count - 2].x, points[points.Count - 2].y), new PointF(points[points.Count - 1].x, points[points.Count - 1].y), graphics);
            }
            else if (points.Count == 2)
            {
                graphics.DrawLine(pen, points[points.Count - 2].x, points[points.Count - 2].y, points[points.Count - 1].x, points[points.Count - 1].y);
            }
            else
            {
                graphics.DrawLine(pen, points[points.Count - 1].x, points[points.Count - 1].y, points[points.Count - 1].x+1, points[points.Count - 1].y+1);
            }
}

其实以上思路最主要的还是增加坐标点和减坐标点。以下就是全部代码,复制粘贴即可使用。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace RedrawUITest
{

    public partial class Form6 : Form
    {

        private BezierPen bezierPen = new BezierPen();

        List<PointF> listpoint = new List<PointF>();
        public Form6()
        {
            InitializeComponent();
            this.DoubleBuffered = true;
            this.MouseDown += BezierPenForm_MouseDown;
            this.MouseMove += BezierPenForm_MouseMove;
            this.MouseUp += BezierPenForm_MouseUp;

            
        }
        PointF startpoint;
        Bitmap bitmap;
        private void BezierPenForm_MouseDown(object sender, MouseEventArgs e)
        {
            bezierPen.AddPoint(e.X, e.Y);
            startpoint = new PointF(e.X,e.Y);
           
        }

        private void BezierPenForm_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Console.WriteLine(e.X+","+e.Y);

                double lineline = Math.Sqrt(Math.Pow((e.X - startpoint.X), 2) + Math.Pow((e.Y - startpoint.Y), 2));
                if (lineline >= 10)
                {
                    bezierPen.AddPoint(e.X, e.Y);
                    startpoint = new PointF(e.X, e.Y);
                    //bezierPen.Draw2(this.CreateGraphics());
                    bezierPen.Draw3(this.CreateGraphics());

                }

            }
        }

        private void BezierPenForm_MouseUp(object sender, MouseEventArgs e)
        {

            Graphics g = Graphics.FromImage(bitmap);
            bezierPen.Draw2(g);
            bezierPen.ClearPoint();
            this.Invalidate();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            if (bitmap != null)
            {
                e.Graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed; //高像素偏移质量
                e.Graphics.CompositingQuality = CompositingQuality.HighSpeed;
                e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
                e.Graphics.DrawImage(bitmap, 0, 0);
               
            }           
        }

        private void Form6_Load(object sender, EventArgs e)
        {
            bitmap = new Bitmap(this.Width, this.Height);
        }
    }


    public class BezierPen
    {
        private List<pendraw> points = new List<pendraw>();
      

        public void AddPoint(float x, float y)
        {
            pendraw pdraw = new pendraw();
            pdraw.x = x;
            pdraw.y = y;
          
            points.Add(pdraw);
        }

        public void ClearPoint() 
        {
            points.Clear();
        }

        public void Draw2(Graphics graphics)
        {
            if (points.Count < 1)
            {
                return;
            }
            Pen pen = new Pen(Color.Red, 7.0f);
            pen.LineJoin = LineJoin.Round;
            pen.StartCap = LineCap.Round;
            pen.EndCap = LineCap.Round;
            graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed; //高像素偏移质量
            graphics.CompositingQuality = CompositingQuality.HighSpeed;
            graphics.SmoothingMode = SmoothingMode.AntiAlias;
            if (points.Count >= 3)
            {
               
                if (points.Count > 4)
                {
                    for (int i = 0; i < points.Count - 4; i++)
                    {
                        graphics.DrawBezier(pen, new PointF(points[i].x, points[i].y), new PointF(points[i + 1].x, points[i + 1].y), new PointF(points[i + 2].x, points[i + 2].y), new PointF(points[i + 3].x, points[i + 3].y));
                    }
                }
                else if (points.Count > 2 && points.Count < 5)
                {
                    for (int i = 0; i < points.Count - 2; i++)
                    {

                        graphics.DrawLine(pen, points[i].x, points[i].y, points[i + 1].x, points[i + 1].y);
                    }
                }
                Splitline(new PointF(points[points.Count - 2].x, points[points.Count - 2].y), new PointF(points[points.Count - 1].x, points[points.Count - 1].y), graphics);
            }
            else if (points.Count == 2)
            {
                graphics.DrawLine(pen, points[points.Count - 2].x, points[points.Count - 2].y, points[points.Count - 1].x , points[points.Count - 1].y );
            }
            else
            {
                graphics.DrawLine(pen, points[points.Count - 1].x, points[points.Count - 1].y, points[points.Count - 1].x+1 , points[points.Count - 1].y+1);
            }
           
        }

        public void Draw3(Graphics graphics)
        {
            if (points.Count < 1) {
                return;
            }   
            Pen pen = new Pen(Color.Red,7.0f);
            graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed; //高像素偏移质量
            graphics.CompositingQuality = CompositingQuality.HighSpeed;
            graphics.SmoothingMode = SmoothingMode.AntiAlias;
            pen.LineJoin = LineJoin.Round;
            pen.StartCap = LineCap.Round;
            pen.EndCap = LineCap.Round;
            //graphics.DrawLine(pen, points[points.Count-2].x, points[points.Count-2].y, points[points.Count-1].x, points[points.Count - 1].y);
            if (points.Count >= 3)
            {
                if (points.Count > 4)
                {
                    graphics.DrawBezier(pen, new PointF(points[points.Count - 5].x, points[points.Count - 5].y), new PointF(points[points.Count - 4].x, points[points.Count - 4].y), new PointF(points[points.Count - 3].x, points[points.Count - 3].y), new PointF(points[points.Count - 2].x, points[points.Count - 2].y));
                }
                else
                {
                    graphics.DrawLine(pen, points[points.Count - 3].x, points[points.Count - 3].y, points[points.Count - 2].x, points[points.Count - 2].y);
                }
                Splitline(new PointF(points[points.Count - 2].x, points[points.Count - 2].y), new PointF(points[points.Count - 1].x, points[points.Count - 1].y), graphics);
            }
            else if (points.Count == 2)
            {
                graphics.DrawLine(pen, points[points.Count - 2].x, points[points.Count - 2].y, points[points.Count - 1].x, points[points.Count - 1].y);
            }
            else
            {
                graphics.DrawLine(pen, points[points.Count - 1].x, points[points.Count - 1].y, points[points.Count - 1].x+1, points[points.Count - 1].y+1);
            }
        }
        void Splitline(PointF point1, PointF point2, Graphics g)
        {
            double fz = 2.5;

            double lineline = Math.Sqrt(Math.Pow((point2.X - point1.X), 2) + Math.Pow((point2.Y - point1.Y), 2));
            if (lineline > fz)
            {
                int num = Convert.ToInt32(lineline / fz);
                List<PointF> points = new List<PointF>();
                double doublex = (point2.X - point1.X) / num;
                double doubley = (point2.Y - point1.Y) / num;
                for (int i = 0; i < num; i++)
                {
                    PointF pointF = new PointF(point1.X + (float)(i * doublex), point1.Y + (float)(i * doubley));
                    points.Add(pointF);
                }
                Console.WriteLine("总数:"+points.Count);
                float widtline = 7.0f;
                float widthlinedj = widtline / points.Count;
                for (int i = 0; i < points.Count - 1; i++)
                {
                    widtline = widtline - widthlinedj;
                    Pen pen = new Pen(Color.Red, widtline);
                    g.DrawLine(pen, points[i], points[i + 1]);
                }
            }
        }
    }

    public class pendraw
    {
        public float x { get; set; }
        public float y { get; set; }

      
    }
}

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值