Представьте, что у вас есть холст, который вы хотите масштабировать до очень высокого значения, а затем разрешить панорамирование.
Хорошим примером является географический инструмент, который должен позволять панорамирование с уровнями "масштабирования" изпротяженность всей земли до нескольких метров.
Я обнаружил, что если вы увеличите масштаб до, скажем, 500 000, перевод станет очень неустойчивым, но ТОЛЬКО если вы просматриваете далеко от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;
}
}
}