欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

WPF 坐标投影

程序员文章站 2022-05-27 16:46:24
...

WPF 坐标投影

有些时候,我们需要自己来制作一个画板,并在画板上绘制我们想要的内容(画图、状态图、统计图等)。此次给大家介绍一下自制画板。

建立画板

建立一个画板,并在画板中建立一个绘图区域TragetsCanvas,并用10X10px的小方格进行分割,添加刻度画板ScaleCanvas,刻度画板与绘图区域之间存在一些间隔,这些间隔用于填充坐标等分割信息。

 <Canvas Width="1300" Height="2600" Background="#FF0E3151">

                        <Border Width="1" Canvas.Top="0" Canvas.Left="650" Background="#5500B6FB" Height="2600"/>
                        <Canvas x:Name="ScaleCanvas" Width="1300" Height="2600">

                        </Canvas>

                        <Canvas Width="1000" Height="2500" Canvas.Left="150" Canvas.Top="10" ClipToBounds="True">

                            <Rectangle Width="1000" Height="2500">
                                <Rectangle.Fill>
                                    <DrawingBrush Viewport="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile" Opacity="1">
                                        <DrawingBrush.Drawing>
                                            <DrawingGroup>
                                                <GeometryDrawing Brush="#20A0BAB0">
                                                    <GeometryDrawing.Geometry>
                                                        <RectangleGeometry Rect="0,0 10,1" />
                                                    </GeometryDrawing.Geometry>
                                                </GeometryDrawing>
                                                <GeometryDrawing Brush="#20A0BAB0">
                                                    <GeometryDrawing.Geometry>
                                                        <RectangleGeometry Rect="0,0 1,10" />
                                                    </GeometryDrawing.Geometry>
                                                </GeometryDrawing>
                                            </DrawingGroup>
                                        </DrawingBrush.Drawing>
                                    </DrawingBrush>
                                </Rectangle.Fill>
                            </Rectangle>

                            <Canvas Width="1000" Height="2500" x:Name="TragetsCanvas">


                            </Canvas>
                        </Canvas>
                    </Canvas>

坐标系转换

我们实际的坐标与设备的坐标一般情况下是不同的,设备默认坐标系的原点(0,0)在左上角,横轴(X)向右为正方向,竖轴(Y)向下为正方向。


    /// <summary>
    /// 坐标系
    /// </summary>
    public class CoordinateTranslation
    {
        // 整个宽度 px
        double hallUiWidth = 1000;
        // 整个高度 px
        double hallUiHeight = 2500;


        double actualMinW = -50;
        double actualMaxW = 50;
        double actualMaxH = 250;
        double actualMinH = 0;

        /// <summary>
        /// True水平坐标从左到右-50~50   False反之50~-50
        /// </summary>
        public bool IsSmallToLargeLtoR { get; set; } = false;

        public double TranslateToUiX(double x)
        {
            double result = 0;

            // 判断当前坐标X在宽度上的比例
            double rate = hallUiWidth / (actualMaxW - actualMinW);

            if (IsSmallToLargeLtoR)
            {

                result = ((x - actualMinW) * rate);
            }
            else
            {
                result = (hallUiWidth - ((x - actualMinW) * rate));
            }
            return CenterTranslateX(result);
        }

        public double TranslateToUiY(double y)
        {
            double result = 0;

            // 判断当前坐标Y在高度度上的比例
            double rate = hallUiHeight / (actualMaxH - actualMinH);

            result = hallUiHeight - ((y - actualMinH) * rate);

            return CenterTranslateY(result);
        }


        // 目标的整体宽度
        double targetWidth = 50;
        // 目标的整体高度
        double targetHeight = 100;

        /// <summary>
        /// 目标的方块显示高度
        /// </summary>
        public double CubeHeight { get; set; } = 40;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="x">目标在坐标轴上的坐标X(目标的左上角坐标X)</param>
        /// <returns></returns>
        private double CenterTranslateX(double x)
        {
            double result = 0;

            result = x - targetWidth / 2.0;

            return result;

        }

        private double CenterTranslateY(double y)
        {
            double result = 0;

            result = y - (targetHeight / 2.0 + CubeHeight / 2.0);

            return result;

        }

    }

坐标系和我们刻度信息是息息相关的。

添加刻度信息

在构造函数中添加刻度信息,函数如下所示:

 /// <summary>
        /// 初始化刻度
        /// </summary>
        private void InitScale()
        {
            // y轴上偏移
            double yOffset = 10;
            // x轴上偏移
            double xOffset = 150;

            // 整个宽度 px
            double hallWidth = 1000;
            // 整个高度 px
            double hallHeight = 2500;

            // 大刻度间隔 px
            double rate = 100;

            // 水平刻度最小
            double hScale = -50;

            // 垂直刻度最小
            double vScale = 0;

            // 水平坐标从左到右-50~50   反之50~-50
            bool isHorizontalSmallToLarge = true;

            if (isHorizontalSmallToLarge)
            {
                for (int i = 0; i <= 10; i++)
                {
                    TextBlock text = new TextBlock();
                    text.Foreground = Brushes.Gray;



                    string tt = (hScale + i * 10).ToString();
                    text.Text = tt;

                    ScaleCanvas.Children.Add(text);
                    double s = ((tt.Length * text.FontSize) / 4.0);
                    double x = i * rate + xOffset;
                    Canvas.SetLeft(text, x - s);
                    Canvas.SetTop(text, hallHeight + yOffset + 10);
                    Line line = new Line() { Stroke = new SolidColorBrush(Color.FromArgb(99, 0, 0xB6, 0xFB)), StrokeThickness = 1 };
                    if (i == 5)
                    {
                        line.X1 = x;
                        line.X2 = x;
                        line.Y1 = 0;
                        line.Y2 = 2600;
                    }
                    else
                    {
                        line.X1 = x;
                        line.X2 = x;
                        line.Y1 = yOffset;
                        line.Y2 = yOffset + hallHeight;
                    }
                    ScaleCanvas.Children.Add(line);
                }
            }
            else
            {
                for (int i = 0; i <= 10; i++)
                {
                    TextBlock text = new TextBlock();
                    text.Foreground = Brushes.Gray;

                    string tt = ((-hScale) - i * 10).ToString();
                    text.Text = tt;

                    ScaleCanvas.Children.Add(text);
                    double s = ((tt.Length * text.FontSize) / 4.0);
                    double x = i * rate + xOffset;
                    Canvas.SetLeft(text, x - s);
                    Canvas.SetTop(text, hallHeight + yOffset + 10);
                    Line line = new Line() { Stroke = new SolidColorBrush(Color.FromArgb(99, 0, 0xB6, 0xFB)), StrokeThickness = 1 };
                    if (i == 5)
                    {
                        line.X1 = x;
                        line.X2 = x;
                        line.Y1 = 0;
                        line.Y2 = 2600;
                    }
                    else
                    {
                        line.X1 = x;
                        line.X2 = x;
                        line.Y1 = yOffset;
                        line.Y2 = yOffset + hallHeight;
                    }
                    ScaleCanvas.Children.Add(line);
                }
            }
            for (int i = 0; i <= 25; i++)
            {
                TextBlock text = new TextBlock() { TextAlignment = TextAlignment.Right, Width = 90 };
                text.Foreground = Brushes.Gray;
                string tt = (vScale + i * 10).ToString();
                text.Text = tt;

                ScaleCanvas.Children.Add(text);
                double s = ((text.FontSize) / 4.0);
                double y = 2500 - (i * rate - yOffset);
                Canvas.SetLeft(text, 50);
                Canvas.SetTop(text, y - s);

                // 右边刻度
                TextBlock text2 = new TextBlock() { TextAlignment = TextAlignment.Left, Width = 90 };
                text2.Foreground = Brushes.Gray;
                text2.Text = tt;
                ScaleCanvas.Children.Add(text2);
                Canvas.SetLeft(text2, hallWidth + xOffset + 10);
                Canvas.SetTop(text2, y - s);


                Line line = new Line() { Stroke = new SolidColorBrush(Color.FromArgb(99, 0, 0xB6, 0xFB)), StrokeThickness = 1 };

                // 第一条占满
                if (i == 0)
                {
                    line.X1 = 0;
                    line.X2 = 1300;
                    line.Y1 = y;
                    line.Y2 = y;
                }
                else
                {
                    line.X1 = xOffset;
                    line.X2 = xOffset + hallWidth;
                    line.Y1 = y;
                    line.Y2 = y;
                }

                ScaleCanvas.Children.Add(line);
            }

        }

效果

WPF 坐标投影


积跬步以至千里:) (:一阵没来由的风