在WPF中更改Canvas的坐标系

Dyl*_*lan 18 c# wpf xaml wpf-controls

我正在编写一个使用Canvas定位元素的地图应用程序.对于每个元素,我必须以编程方式将元素的Lat/Long转换为画布的坐标,然后设置Canvas.Top和Canvas.Left属性.

如果我有一个360x180画布,我可以将画布上的坐标转换为X轴上的-180到180而不是0到360,而Y轴上的90到-90而不是0到180?

扩展要求:

  • 画布可以是任何尺寸,因此如果它是360x180或5000x100仍然可以使用.
  • Lat/Long区域可能不总是(-90,-180)x(90,180),它可以是任何东西(即(5,-175)x(89,-174)).
  • 像PathGeometry这样的元素是基点,而不是基于Canvas.Top/Left的元素需要工作.

Rya*_*ndy 6

这是一个全XAML解决方案.好吧,主要是XAML,因为你必须在代码中使用IValueConverter.所以:创建一个新的WPF项目并为其添加一个类.该类是MultiplyConverter:

namespace YourProject
{
    public class MultiplyConverter : System.Windows.Data.IValueConverter
    {
        public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return AsDouble(value)* AsDouble(parameter);
        }
        double AsDouble(object value)
        {
            var valueText = value as string;
            if (valueText != null)
                return double.Parse(valueText);
            else
                return (double)value;
        }

        public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new System.NotSupportedException();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后将此XAML用于您的Window.现在,您应该在XAML预览窗口中看到结果.

编辑:您可以通过将您的画布放在另一个画布中来解决背景问题.有点奇怪,但它的确有效.另外,我添加了一个ScaleTransform,它翻转Y轴,使正Y向上,负向向下.请注意哪些名称去哪里:

<Canvas Name="canvas" Background="Moccasin">
    <Canvas Name="innerCanvas">
        <Canvas.RenderTransform>
            <TransformGroup>
                <TranslateTransform x:Name="translate">
                    <TranslateTransform.X>
                        <Binding ElementName="canvas" Path="ActualWidth"
                                Converter="{StaticResource multiplyConverter}" ConverterParameter="0.5" />
                    </TranslateTransform.X>
                    <TranslateTransform.Y>
                        <Binding ElementName="canvas" Path="ActualHeight"
                                Converter="{StaticResource multiplyConverter}" ConverterParameter="0.5" />
                    </TranslateTransform.Y>
                </TranslateTransform>
                <ScaleTransform ScaleX="1" ScaleY="-1" CenterX="{Binding ElementName=translate,Path=X}"
                        CenterY="{Binding ElementName=translate,Path=Y}" />
            </TransformGroup>
        </Canvas.RenderTransform>
        <Rectangle Canvas.Top="-50" Canvas.Left="-50" Height="100" Width="200" Fill="Blue" />
        <Rectangle Canvas.Top="0" Canvas.Left="0" Height="200" Width="100" Fill="Green" />
        <Rectangle Canvas.Top="-25" Canvas.Left="-25" Height="50" Width="50" Fill="HotPink" />
    </Canvas>
</Canvas>
Run Code Online (Sandbox Code Playgroud)

至于你需要不同范围的新要求,更复杂的ValueConverter可能会有所帮助.


Moj*_*ter 0

我很确定你不能完全做到这一点,但是有一个从纬度/经度转换为画布坐标的方法是非常简单的。

Point ToCanvas(double lat, double lon) {
  double x = ((lon * myCanvas.ActualWidth) / 360.0) - 180.0;
  double y = ((lat * myCanvas.ActualHeight) / 180.0) - 90.0;
  return new Point(x,y);
}
Run Code Online (Sandbox Code Playgroud)

(或类似的规定)