zoukankan      html  css  js  c++  java
  • WPF中的画笔功能,实现直实线、弯实线、直虚线、弯虚线

    1、InkCanvas类。

    实现画板需要用到InkCanvas。一般情况下不需任何代码就可以在上面画线了。

    如果需要设置画笔颜色、笔尖大小等就需要设置DefaultDrawingAttributes,例如:

    DrawingAttributes attributes = new DrawingAttributes();
    attributes.Color = Colors.Black;
    attributes.Height = 50;
    attributes.Width = 50;
    attributes.FitToCurve = true;
    

    2、在InkCanvas上画直线

    方法:在StrokeCollected事件中进行修正,StrokeCollected事件在单个笔画结束后触发。可以取出笔画的起始点(BeginPoint)和终点(EndPoint),然后使用该两点新建笔画即可。

    代码如下:

     private void InkCanvas_StrokeCollected(object sender, InkCanvasStrokeCollectedEventArgs e)
            {
                if (e.Stroke.StylusPoints.Count > 1)
                {
                    UpdateLine(e.Stroke);
                }
            }
    private void UpdateLine(Stroke currentStroke)
            {
                StylusPoint beginPoint = currentStroke.StylusPoints[0];//起始点
                StylusPoint endPoint = currentStroke.StylusPoints.Last();//终点
                packageCanvas.Strokes.Remove(currentStroke);//移除原来的笔画
                List<Point> pointList = new List<Point>();
                pointList.Add(new Point(beginPoint.X, beginPoint.Y));
                pointList.Add(new Point(endPoint.X, endPoint.Y));
                StylusPointCollection point = new StylusPointCollection(pointList);
                Stroke stroke = new Stroke(point);//用两点实现笔画
                stroke.DrawingAttributes = packageCanvas.DefaultDrawingAttributes.Clone();
                InkCanvas.Strokes.Add(stroke);           
    }
    

    3、在InkCanvas上画直虚线

    方法:还是跟上面一样取起始点和终点,不同点是:在两点间绘制许多点,然后将相邻的两点连接成一个笔画。这样一个直虚线变好了。

    代码如下:

    private void UpdateLine(Stroke currentStroke)
    {
          InkCanvas.Strokes.Remove(currentStroke);//移除原来笔画
                    int dotTime = 0;
                    int intervalLen=6;//步长
                    double lineLen = Math.Sqrt(Math.Pow(beginPoint.X - endPoint.X, 2) + Math.Pow(beginPoint.Y - endPoint.Y, 2));//线的长度
                    Point currentPoint = new Point(beginPoint.X, beginPoint.Y);
                    double relativaRate = Math.Abs(endPoint.Y - beginPoint.Y) * 1.0 / Math.Abs(endPoint.X - beginPoint.X);
                    double angle = Math.Atan(relativaRate) * 180 / Math.PI;//直线的角度大小,无需考虑正负
                    int xOrientation = endPoint.X > beginPoint.X ? 1 : -1;//判断新生成点的X轴方向
                    int yOrientation = endPoint.Y > beginPoint.Y ? 1 : -1;
                    if (lineLen < intervalLen)
                    {
                        return;
                    }
                    while (dotTime * intervalLen < lineLen)
                    {
                        double x = currentPoint.X + dotTime * intervalLen * Math.Cos(angle * Math.PI / 180) * xOrientation;
                        double y = currentPoint.Y + dotTime * intervalLen * Math.Sin(angle * Math.PI / 180) * yOrientation; 
                        List<Point> pL = new List<Point>();
                        pL.Add(new Point(x, y));
                        x += intervalLen * Math.Cos(angle * Math.PI / 180) * xOrientation;
                        y += intervalLen * Math.Sin(angle * Math.PI / 180) * yOrientation;
                        pL.Add(new Point(x, y));
                        StylusPointCollection spc = new StylusPointCollection(pL);//相邻两点作为一个笔画
                        Stroke stroke = new Stroke(spc);
                        stroke.DrawingAttributes = packageCanvas.DefaultDrawingAttributes.Clone();
                        InkCanvas.Strokes.Add(stroke);
                        dotTime+=2;
                    }
    }
    

    4、在InkCanvas上画弯虚线

    方法:在InkCanvas_StrokeCollected方法的参数属性中可以获得线上的点的坐标。

    2)生成StylusPointCollection collection=currentStroke.StylusPoints,用来存放当前笔画的所有点

    2)生成一个List<Point> allPointList,用来存放最终生成的点

    2) 将起始点=》allPointList,起始点-》currentPoint

    3)遍历collection,IF currentPoint与找到点(item)的距离==步长 THEN item=>allPointList;item=>currentPoint,取下一个点

    IF currentPoint与找到点(item)的距离>步长 THEN 在currentPoint与item线上找到一个点,使得与currentPoint的距离=步长,item=>allPointList;item=>currentPoint,继续当前点

    IF currentPoint与找到点(item)的距离<步长 取下一个点

    代码如下:

    private void UpdateLine(Stroke currentStroke)
    {
    InkCanvas.Strokes.Remove(currentStroke);
                    StylusPointCollection collection = currentStroke.StylusPoints;
                    List<Point> allSelectedPoint = new List<Point>();
                    Point currentPoint = new Point(collection[0].X, collection[0].Y);
                    allSelectedPoint.Add(currentPoint);
                    for (int i = 0; i < collection.Count; i++)
                    {
                        var item = collection[i];
                        double length = Math.Sqrt(Math.Pow(item.X - currentPoint.X, 2) + Math.Pow(item.Y - currentPoint.Y, 2));
                        if ((int)(length + 0.5) == (int)intervalLen || length == intervalLen)
                        {
    
                            currentPoint = new Point(item.X, item.Y);
                            allSelectedPoint.Add(currentPoint);
                        }
                        else if (length > intervalLen)
                        {
                            double relativaRate = Math.Abs(item.Y - currentPoint.Y) * 1.0 / Math.Abs(item.X - currentPoint.X);
                            double angle = Math.Atan(relativaRate) * 180 / Math.PI;
                            int xOrientation = item.X > currentPoint.X ? 1 : -1;
                            int yOrientation = item.Y > currentPoint.Y ? 1 : -1;
                            double x = currentPoint.X + intervalLen * Math.Cos(angle * Math.PI / 180) * xOrientation;
                            double y = currentPoint.Y + intervalLen * Math.Sin(angle * Math.PI / 180) * yOrientation;
                            currentPoint = new Point(x, y);
                            allSelectedPoint.Add(currentPoint);
                            i--;//很重要,继续当前点
                        }
                    }
                    for (int j = 0; j < allSelectedPoint.Count; j++)
                    {
                        List<Point> p = new List<Point>();
                        p.Add(allSelectedPoint[j]);
                        if (j < allSelectedPoint.Count - 1)
                        {
                            j++;
                        }
                        p.Add(allSelectedPoint[j]);
                        StylusPointCollection spc = new StylusPointCollection(p);
                        Stroke stroke = new Stroke(spc);
                        InkCanvas.Strokes.Add(stroke);
                    }
    }
    

    以上是测试过的代码,不足之处是:只能在当前笔画完成后在进行修正,因为代码写在InkCanvas_StrokeCollected中。

  • 相关阅读:
    利用pipe实现进程通信一例
    司机和售票员问题 信号signal注册一例
    HDU 1003
    HDU 1847
    HDU 1846(巴什博弈)
    《断弦》感想
    夺冠概率
    熄灯问题
    HDU 2176(Nim博弈)
    NYOJ 541
  • 原文地址:https://www.cnblogs.com/smallstone/p/1947021.html
Copyright © 2011-2022 走看看