WPF 坐标投影

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

        }

效果

在这里插入图片描述


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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值