在高比例因子下翻译WPF画布是';我们不能顺利地离开原点
假设您有一个画布,希望将其缩放到非常高的值,然后允许“平移” 一个很好的例子是地理工具,它需要允许使用“缩放”级别从整个地球范围向下平移几米 我发现,如果你放大到超过,比如说500000,翻译会变得非常不稳定,但前提是你的视角远离画布的0,0原点 我尝试过使用画布的RenderTransform进行翻译,我尝试过在缩放的画布上移动另一个画布。我在其他人的在线示例应用程序中也看到了同样的问题 下面的示例代码提供了在两个不同的缩放位置进行平移(单击并拖动)。如果您实现了该代码,您可以点击一个按钮放大到0,0,在那里您将发现漂亮、平滑的鼠标平移。然后使用另一个按钮放大到200,200,平滑平移就不存在了 你知道为什么会这样,或者怎样才能解决它吗 样本的XAML:在高比例因子下翻译WPF画布是';我们不能顺利地离开原点,wpf,transform,scale,Wpf,Transform,Scale,假设您有一个画布,希望将其缩放到非常高的值,然后允许“平移” 一个很好的例子是地理工具,它需要允许使用“缩放”级别从整个地球范围向下平移几米 我发现,如果你放大到超过,比如说500000,翻译会变得非常不稳定,但前提是你的视角远离画布的0,0原点 我尝试过使用画布的RenderTransform进行翻译,我尝试过在缩放的画布上移动另一个画布。我在其他人的在线示例应用程序中也看到了同样的问题 下面的示例代码提供了在两个不同的缩放位置进行平移(单击并拖动)。如果您实现了该代码,您可以点击一个按钮放大
<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;
}
}
}