Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在高比例因子下翻译WPF画布是';我们不能顺利地离开原点_Wpf_Transform_Scale - Fatal编程技术网

在高比例因子下翻译WPF画布是';我们不能顺利地离开原点

在高比例因子下翻译WPF画布是';我们不能顺利地离开原点,wpf,transform,scale,Wpf,Transform,Scale,假设您有一个画布,希望将其缩放到非常高的值,然后允许“平移” 一个很好的例子是地理工具,它需要允许使用“缩放”级别从整个地球范围向下平移几米 我发现,如果你放大到超过,比如说500000,翻译会变得非常不稳定,但前提是你的视角远离画布的0,0原点 我尝试过使用画布的RenderTransform进行翻译,我尝试过在缩放的画布上移动另一个画布。我在其他人的在线示例应用程序中也看到了同样的问题 下面的示例代码提供了在两个不同的缩放位置进行平移(单击并拖动)。如果您实现了该代码,您可以点击一个按钮放大

假设您有一个画布,希望将其缩放到非常高的值,然后允许“平移”

一个很好的例子是地理工具,它需要允许使用“缩放”级别从整个地球范围向下平移几米

我发现,如果你放大到超过,比如说500000,翻译会变得非常不稳定,但前提是你的视角远离画布的0,0原点

我尝试过使用画布的RenderTransform进行翻译,我尝试过在缩放的画布上移动另一个画布。我在其他人的在线示例应用程序中也看到了同样的问题

下面的示例代码提供了在两个不同的缩放位置进行平移(单击并拖动)。如果您实现了该代码,您可以点击一个按钮放大到0,0,在那里您将发现漂亮、平滑的鼠标平移。然后使用另一个按钮放大到200,200,平滑平移就不存在了

你知道为什么会这样,或者怎样才能解决它吗

样本的XAML:

<Window x:Class="TestPanZoom.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="500" Width="500" Loaded="Window_Loaded">
    <Grid PreviewMouseLeftButtonDown="Grid_PreviewMouseLeftButtonDown" MouseMove="Grid_MouseMove">
        <Canvas Name="canvas1"></Canvas>
        <Button Height="31" 
                Name="button1" 
                Click="button1_Click" 
                Margin="12,12,0,0" 
                VerticalAlignment="Top" 
                HorizontalAlignment="Left" Width="270">
            Zoom WAY in to 0,0 and get smooth panning
        </Button>
        <Button Height="31" 
                Name="button2" 
                Click="button2_Click" 
                Margin="12,49,0,0" 
                VerticalAlignment="Top" 
                HorizontalAlignment="Left" 
                Width="270">
            Zoom WAY in to 200, 200 -- NO smooth panning
        </Button>
    </Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace TestPanZoom
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// Demo of an issue with translate transform when scale is very high
    /// but ONLY when you are far from the canvas's 0,0 origin.
    /// Why?  Is their a fix?
    /// </summary>
    public partial class Window1 : Window
    {
        Point m_clickPoint;

        public Window1()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // Add a 2x2 black ellipse centered at 0,0
            Ellipse el = new Ellipse();
            el.Fill = Brushes.Black;
            el.Width = 2;
            el.Height = 2;
            el.HorizontalAlignment = HorizontalAlignment.Left;
            el.VerticalAlignment = VerticalAlignment.Top;
            el.Margin = new Thickness(0 - el.Width / 2, 0 - el.Height / 2, 0, 0);
            canvas1.Children.Add(el);

            // Add a 1x1 red rectangle with its top/left corner at 0,0
            Rectangle r = new Rectangle();
            r.Fill = Brushes.Red;
            r.Width = 1;
            r.Height = 1;
            r.HorizontalAlignment = HorizontalAlignment.Left;
            r.VerticalAlignment = VerticalAlignment.Top;
            r.Margin = new Thickness(0, 0, 0, 0);
            canvas1.Children.Add(r);


            // Add a 2x2 purple ellipse at a point 200,200
            Point otherPoint = new Point(200, 200);
            el = new Ellipse();
            el.Fill = Brushes.Purple;
            el.Width = 2;
            el.Height = 2;
            el.HorizontalAlignment = HorizontalAlignment.Left;
            el.VerticalAlignment = VerticalAlignment.Top;
            el.Margin = new Thickness(otherPoint.X - el.Width / 2, otherPoint.Y - el.Height / 2, 0, 0);
            canvas1.Children.Add(el);

            // Add a 1x1 blue rectangle with its top/left corner at 200,200
            r = new Rectangle();
            r.Fill = Brushes.Blue;
            r.Width = 1;
            r.Height = 1;
            r.HorizontalAlignment = HorizontalAlignment.Left;
            r.VerticalAlignment = VerticalAlignment.Top;
            r.Margin = new Thickness(otherPoint.X, otherPoint.Y, 0, 0);
            canvas1.Children.Add(r);
        }


        private void Grid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            m_clickPoint = e.GetPosition(this);
        }

        // Pan with the mouse when left-mouse is down
        private void Grid_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                Point mousePosition = e.GetPosition(this);
                double xDiff = mousePosition.X - m_clickPoint.X;
                double yDiff = mousePosition.Y - m_clickPoint.Y;

                TranslateTransform tt = new TranslateTransform(xDiff, yDiff);
                TransformGroup tg = new TransformGroup();
                tg.Children.Add(canvas1.RenderTransform);
                tg.Children.Add(tt);
                canvas1.RenderTransform = tg;

                m_clickPoint = e.GetPosition(this);
            }
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            TransformGroup tg = new TransformGroup();
            double scale = 1000000;
            double xCenter = 0;
            double yCenter = 0;
            double xOffset = (canvas1.ActualHeight / 2.0 - xCenter);
            double yOffset = (canvas1.ActualWidth / 2.0 - yCenter);
            ScaleTransform st = new ScaleTransform(scale, scale);
            st.CenterX = xCenter;
            st.CenterY = yCenter;
            TranslateTransform tt = new TranslateTransform(xOffset, yOffset);
            tg.Children.Add(st);
            tg.Children.Add(tt);
            canvas1.RenderTransform = tg;
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            TransformGroup tg = new TransformGroup();
            double scale = 1000000;
            double xCenter = 200;
            double yCenter = 200;
            double xOffset = (canvas1.ActualHeight / 2.0 - xCenter);
            double yOffset = (canvas1.ActualWidth / 2.0 - yCenter);
            ScaleTransform st = new ScaleTransform(scale, scale);
            st.CenterX = xCenter;
            st.CenterY = yCenter;
            TranslateTransform tt = new TranslateTransform(xOffset, yOffset);
            tg.Children.Add(st);
            tg.Children.Add(tt);
            canvas1.RenderTransform = tg;
        }

    }
}

放大到0,0并获得平滑平移
放大到200200——无平滑平移
样本代码:

<Window x:Class="TestPanZoom.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="500" Width="500" Loaded="Window_Loaded">
    <Grid PreviewMouseLeftButtonDown="Grid_PreviewMouseLeftButtonDown" MouseMove="Grid_MouseMove">
        <Canvas Name="canvas1"></Canvas>
        <Button Height="31" 
                Name="button1" 
                Click="button1_Click" 
                Margin="12,12,0,0" 
                VerticalAlignment="Top" 
                HorizontalAlignment="Left" Width="270">
            Zoom WAY in to 0,0 and get smooth panning
        </Button>
        <Button Height="31" 
                Name="button2" 
                Click="button2_Click" 
                Margin="12,49,0,0" 
                VerticalAlignment="Top" 
                HorizontalAlignment="Left" 
                Width="270">
            Zoom WAY in to 200, 200 -- NO smooth panning
        </Button>
    </Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace TestPanZoom
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// Demo of an issue with translate transform when scale is very high
    /// but ONLY when you are far from the canvas's 0,0 origin.
    /// Why?  Is their a fix?
    /// </summary>
    public partial class Window1 : Window
    {
        Point m_clickPoint;

        public Window1()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // Add a 2x2 black ellipse centered at 0,0
            Ellipse el = new Ellipse();
            el.Fill = Brushes.Black;
            el.Width = 2;
            el.Height = 2;
            el.HorizontalAlignment = HorizontalAlignment.Left;
            el.VerticalAlignment = VerticalAlignment.Top;
            el.Margin = new Thickness(0 - el.Width / 2, 0 - el.Height / 2, 0, 0);
            canvas1.Children.Add(el);

            // Add a 1x1 red rectangle with its top/left corner at 0,0
            Rectangle r = new Rectangle();
            r.Fill = Brushes.Red;
            r.Width = 1;
            r.Height = 1;
            r.HorizontalAlignment = HorizontalAlignment.Left;
            r.VerticalAlignment = VerticalAlignment.Top;
            r.Margin = new Thickness(0, 0, 0, 0);
            canvas1.Children.Add(r);


            // Add a 2x2 purple ellipse at a point 200,200
            Point otherPoint = new Point(200, 200);
            el = new Ellipse();
            el.Fill = Brushes.Purple;
            el.Width = 2;
            el.Height = 2;
            el.HorizontalAlignment = HorizontalAlignment.Left;
            el.VerticalAlignment = VerticalAlignment.Top;
            el.Margin = new Thickness(otherPoint.X - el.Width / 2, otherPoint.Y - el.Height / 2, 0, 0);
            canvas1.Children.Add(el);

            // Add a 1x1 blue rectangle with its top/left corner at 200,200
            r = new Rectangle();
            r.Fill = Brushes.Blue;
            r.Width = 1;
            r.Height = 1;
            r.HorizontalAlignment = HorizontalAlignment.Left;
            r.VerticalAlignment = VerticalAlignment.Top;
            r.Margin = new Thickness(otherPoint.X, otherPoint.Y, 0, 0);
            canvas1.Children.Add(r);
        }


        private void Grid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            m_clickPoint = e.GetPosition(this);
        }

        // Pan with the mouse when left-mouse is down
        private void Grid_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                Point mousePosition = e.GetPosition(this);
                double xDiff = mousePosition.X - m_clickPoint.X;
                double yDiff = mousePosition.Y - m_clickPoint.Y;

                TranslateTransform tt = new TranslateTransform(xDiff, yDiff);
                TransformGroup tg = new TransformGroup();
                tg.Children.Add(canvas1.RenderTransform);
                tg.Children.Add(tt);
                canvas1.RenderTransform = tg;

                m_clickPoint = e.GetPosition(this);
            }
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            TransformGroup tg = new TransformGroup();
            double scale = 1000000;
            double xCenter = 0;
            double yCenter = 0;
            double xOffset = (canvas1.ActualHeight / 2.0 - xCenter);
            double yOffset = (canvas1.ActualWidth / 2.0 - yCenter);
            ScaleTransform st = new ScaleTransform(scale, scale);
            st.CenterX = xCenter;
            st.CenterY = yCenter;
            TranslateTransform tt = new TranslateTransform(xOffset, yOffset);
            tg.Children.Add(st);
            tg.Children.Add(tt);
            canvas1.RenderTransform = tg;
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            TransformGroup tg = new TransformGroup();
            double scale = 1000000;
            double xCenter = 200;
            double yCenter = 200;
            double xOffset = (canvas1.ActualHeight / 2.0 - xCenter);
            double yOffset = (canvas1.ActualWidth / 2.0 - yCenter);
            ScaleTransform st = new ScaleTransform(scale, scale);
            st.CenterX = xCenter;
            st.CenterY = yCenter;
            TranslateTransform tt = new TranslateTransform(xOffset, yOffset);
            tg.Children.Add(st);
            tg.Children.Add(tt);
            canvas1.RenderTransform = tg;
        }

    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
命名空间TestPanZoom
{
/// 
///Window1.xaml的交互逻辑
///演示比例非常高时的平移变换问题
///但仅当您远离画布的0,0原点时。
///为什么?他们的问题解决了吗?
/// 
公共部分类Window1:Window
{
点击点m_点击点;
公共窗口1()
{
初始化组件();
}
已加载私有无效窗口(对象发送器、路由目标)
{
//添加一个以0,0为中心的2x2黑色椭圆
椭圆el=新椭圆();
el.填充=刷子。黑色;
el.宽度=2;
标高高度=2;
el.HorizontalAlignment=HorizontalAlignment.Left;
el.垂直对齐=垂直对齐.顶部;
标高边缘=新厚度(0-标高宽度/2,0-标高高度/2,0,0);
画布1.儿童。添加(el);
//添加一个1x1红色矩形,其上/左角为0,0
矩形r=新矩形();
r、 填充=刷子。红色;
r、 宽度=1;
r、 高度=1;
r、 水平对齐=水平对齐。左;
r、 垂直对齐=垂直对齐。顶部;
r、 边距=新厚度(0,0,0,0);
画布1.儿童。添加(r);
//在点200200处添加2x2紫色椭圆
点otherPoint=新点(200200);
el=新椭圆();
el.Fill=画笔。紫色;
el.宽度=2;
标高高度=2;
el.HorizontalAlignment=HorizontalAlignment.Left;
el.垂直对齐=垂直对齐.顶部;
标高边缘=新厚度(其他点X-标高宽度/2,其他点Y-标高高度/2,0,0);
画布1.儿童。添加(el);
//添加一个1x1蓝色矩形,其左上角位于200200处
r=新矩形();
r、 填充=画笔。蓝色;
r、 宽度=1;
r、 高度=1;
r、 水平对齐=水平对齐。左;
r、 垂直对齐=垂直对齐。顶部;
r、 边距=新厚度(其他点.X,其他点.Y,0,0);
画布1.儿童。添加(r);
}
私有void Grid_PreviewMouseLeftButtonDown(对象发送器,鼠标按钮ventargs e)
{
m_clickPoint=e.GetPosition(这个);
}
//当鼠标左键按下时,用鼠标平移
专用void Grid\u MouseMove(对象发送器,MouseEventArgs e)
{
如果(e.LeftButton==鼠标按钮状态。按下)
{
点鼠标位置=e.GetPosition(此);
double xDiff=mousePosition.X-m_clickPoint.X;
double yDiff=mousePosition.Y-m_clickPoint.Y;
TranslateTransform tt=新的TranslateTransform(xDiff,YDIF);
TransformGroup tg=新TransformGroup();
tg.Children.Add(canvas1.RenderTransform);
tg.Children.Add(tt);
canvas1.RenderTransform=tg;
m_clickPoint=e.GetPosition(这个);
}
}
私有无效按钮1\u单击(对象发送者,路由目标)
{
TransformGroup tg=新TransformGroup();
双刻度=1000000;
双xCenter=0;
双中心=0;
双xOffset=(canvas1.ActualHeight/2.0-xCenter);
双yOffset=(canvas1.ActualWidth/2.0-yCenter);
ScaleTransform st=新的ScaleTransform(缩放,缩放);
st.CenterX=xCenter;
圣CenterY=yCenter;
TranslateTransform tt=新的TranslateTransform(xOffset,yOffset);
tg、Children.Add(st);
tg.Children.Add(tt);
canvas1.RenderTransform=tg;
}
私有无效按钮2\u单击(对象发送者,路由目标)
{
TransformGroup tg=新TransformGroup();
双刻度=1000000;
双xCenter=200;
双中心=200;
双xOffset=(canvas1.ActualHeight/2.0-xCenter);
双yOffset=(canvas1.ActualWidth/2.0-yCenter);
ScaleTransform st=新的ScaleTransform(缩放,缩放);
st.CenterX=xCent
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows;

namespace VisualTest
{
 public class DrawingCanvas : Panel
 {
    private List<Visual> visuals = new List<Visual>();

    protected override Visual GetVisualChild(int index)
    {
        return visuals[index];
    }
    protected override int VisualChildrenCount
    {
        get
        {
            return visuals.Count;
        }
    }

    public void AddVisual(Visual visual)
    {
        visuals.Add(visual);

        base.AddVisualChild(visual);
        base.AddLogicalChild(visual);
    }

    public void DeleteVisual(Visual visual)
    {
        visuals.Remove(visual);

        base.RemoveVisualChild(visual);
        base.RemoveLogicalChild(visual);            
    }

    public DrawingVisual GetVisual(Point point)
    {
        HitTestResult hitResult = VisualTreeHelper.HitTest(this, point);
        return hitResult.VisualHit as DrawingVisual;            
    }

    private List<DrawingVisual> hits = new List<DrawingVisual>();
    public List<DrawingVisual> GetVisuals(Geometry region)
    {
        hits.Clear();
        GeometryHitTestParameters parameters = new GeometryHitTestParameters(region);
        HitTestResultCallback callback = new HitTestResultCallback(this.HitTestCallback);
        VisualTreeHelper.HitTest(this, null, callback, parameters);
        return hits;
    }

    private HitTestResultBehavior HitTestCallback(HitTestResult result)
    {
        GeometryHitTestResult geometryResult = (GeometryHitTestResult)result;
        DrawingVisual visual = result.VisualHit as DrawingVisual;
        if (visual != null &&
            geometryResult.IntersectionDetail == IntersectionDetail.FullyInside)
        {
            hits.Add(visual);
        }
        return HitTestResultBehavior.Continue;
    }

 }
}