gpt4 book ai didi

c# - 在 MultiScaleImage 上保持相对位置

转载 作者:太空宇宙 更新时间:2023-11-03 14:26:07 24 4
gpt4 key购买 nike

在看到 this instructions 后,我实现了以下 Silverlight 应用程序,这是我的代码:

public partial class MainPage : UserControl
{
private Point lastMousePos = new Point();
private double zoom = 1;
private Point lastMouseLogicaPos = new Point();
private Point lastMouseViewPort = new Point();
private bool duringDrag = false;
private bool duringOpen = false;
private List<Dot> dots = new List<Dot>();
private bool addDot = false;

public MainPage()
{
InitializeComponent();

this.MouseMove += delegate(object sender, MouseEventArgs e)
{ this.lastMousePos = e.GetPosition(this.ZoomImage); };

ZoomImage.MouseWheel += new MouseWheelEventHandler(ZoomImage_MouseWheel);
this.ZoomImage.UseSprings = false;
}

private void ZoomImage_MouseWheel(object sender, MouseWheelEventArgs e)
{
double newzoom = zoom;

if (e.Delta > 0)
{ newzoom /= 1.3; }
else
{ newzoom *= 1.3; }

Point logicalPoint = this.ZoomImage.ElementToLogicalPoint(this.lastMousePos);
this.ZoomImage.ZoomAboutLogicalPoint(zoom / newzoom, logicalPoint.X, logicalPoint.Y);

zoom = newzoom;
e.Handled = true;
}

private void ZoomImage_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
lastMouseLogicaPos = e.GetPosition(LayoutRoot);
lastMouseViewPort = this.ZoomImage.ViewportOrigin;

foreach (var dot in this.dots)
{ dot.LastMouseLogicPos = e.GetPosition(LayoutRoot); }

if (!this.addDot)
{ duringDrag = true; }
}

private void ZoomImage_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (this.addDot)
{
Dot dot = new Dot(this.lastMouseLogicaPos.X, this.lastMouseLogicaPos.Y)
{ Name = "Dot" + (this.dots.Count + 1).ToString() };

this.dots.Add(dot);
this.DotCanvas.Children.Add(dot);
}
else
{ duringDrag = false; }
}

private void ZoomImage_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (duringDrag)
{
double zoomFactor = 1 / this.ZoomImage.ViewportWidth;
Point newPoint = lastMouseViewPort;
Point thisMouseLogicalPos = e.GetPosition(LayoutRoot);
newPoint.X += (lastMouseLogicaPos.X - thisMouseLogicalPos.X) / (this.ZoomImage.ActualWidth * zoomFactor);
newPoint.Y += (lastMouseLogicaPos.Y - thisMouseLogicalPos.Y) / (this.ZoomImage.ActualWidth * zoomFactor);
this.ZoomImage.ViewportOrigin = newPoint;

foreach (var dot in this.dots)
{
Point dotLogicPoint = this.ZoomImage.ElementToLogicalPoint(new Point(dot.X, dot.Y));
thisMouseLogicalPos = e.GetPosition(LayoutRoot);

dotLogicPoint.X -= (dot.LastMouseLogicPos.X - thisMouseLogicalPos.X) / ((1 / 1.8) * this.ZoomImage.ViewportWidth);
dotLogicPoint.Y -= (dot.LastMouseLogicPos.Y - thisMouseLogicalPos.Y) / (this.ZoomImage.ActualWidth * this.ZoomImage.ViewportWidth);

dot.X = (this.ZoomImage.LogicalToElementPoint(locLogicPoint).X);
dot.Y = (this.ZoomImage.LogicalToElementPoint(locLogicPoint).Y);
}
}
}

private void ZoomImage_ImageOpenSucceeded(object sender, System.Windows.RoutedEventArgs e)
{ duringOpen = true; }

private void ZoomImage_MotionFinished(object sender, System.Windows.RoutedEventArgs e)
{
if (duringOpen)
{ duringOpen = false; }
}

private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
this.addDot = !this.addDot;

if (this.addDot)
{ this.btnAddDot.Content = "Click on Image"; }
else
{ this.btnAddDot.Content = "Add Dot"; }
}
}

有了它,我可以在 MultiScaleImage 上缩放和平移,并将我的自定义 Dot 对象添加到 DotCanvas Canvas 。这是 XAML:

<UserControl x:Class="DeepZoomSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400" Width="800" Height="600">

<Grid x:Name="LayoutRoot" Background="Black" Margin="0,0,-98,-86">

<MultiScaleImage x:Name="ZoomImage" Source="GeneratedImages/dzc_output.xml"
Margin="8,8,0,0" MouseLeftButtonDown="ZoomImage_MouseLeftButtonDown"
MouseLeftButtonUp="ZoomImage_MouseLeftButtonUp" MouseMove="ZoomImage_MouseMove" ImageOpenSucceeded="ZoomImage_ImageOpenSucceeded"
MotionFinished="ZoomImage_MotionFinished" Height="584" VerticalAlignment="Top" HorizontalAlignment="Left" Width="784"/>

<Canvas x:Name="DotCanvas" HorizontalAlignment="Left" Height="584" Margin="8" VerticalAlignment="Top" Width="784" MouseLeftButtonUp="LocationCanvas_MouseLeftButtonUp"/>
<Button x:Name="btnAddDot" Content="Add Location" HorizontalAlignment="Right" Height="44" Margin="0,0,24,24" VerticalAlignment="Bottom" Width="112" Click="Button_Click"/>

</Grid>

现在的问题是,由于点位于 MultiScateImage(ZoomImage 对象)上方的 Canvas 中,当我平移和缩放时,点将留在 Canvas 上各自的位置。此代码尝试在平移和缩放图像时将点保持在原位的尝试有一些遗漏。

这是应用程序的图像,周围的蓝点是我的自定义 Dot 对象:

alt text

主要问题是,当用户缩放和平移时,我如何才能将点保持在图像上的相对位置。

最佳答案

这很棘手,但绝对可以做到,我最近为类似的应用程序做了同样的事情。我不会撒谎,我花了好几个小时才开始工作,所以请准备好让人头疼。

基本上涉及两件事:

<强>1。将点定位在正确的位置

在这里,数学是你的 friend 。您将必须创建一些方法,将基于 multiScaleImage 的坐标转置到您的 Canvas (即视口(viewport))坐标。

首先,您必须深入了解 ViewPortOrigin 和 ViewPortWidth(this 是一个很好的开始)。他们有一些注意事项(例如,我似乎记得 viewPortHeight 必须乘以图像比率才能获得实际值 - 或类似的东西)。

为您指出解决方案:您必须减去 viewPortOrigin 并乘以/除以 viewPortWidth。如果您有耐心(并且很幸运 ;-) )今晚我会查看我的项目并发布一些代码,但如果您真正理解这些参数就很好了 - 否则调试和故障排除将很棘手。

帮助我理解发生了什么的事情是在周围放置一些文本 block 并显示 viewportWidth/Origin/等。一直在导航多尺度图像时。

编辑:你很幸运,我记得这个 - 所以这里有一些代码应该有用。同样,我建议您不要在没有理解的情况下只是复制和粘贴,因为您不会走那么远。

private Point CanvasToDeepZoom(MultiScaleImage msi, Point absoluteInsideCanvas)
{
// the only non-logical (to me) step: viewportOrigin.Y must be multiplied by the aspectRatio
var ViewportHeight = msi.ViewportWidth * msi.AspectRatio * msi.ActualHeight / msi.ActualWidth;

var relativeToCanvas = new Point(
absoluteInsideCanvas.X / msi.ActualWidth,
absoluteInsideCanvas.Y / msi.ActualHeight);

return new Point(
msi.ViewportOrigin.X + msi.ViewportWidth * relativeToCanvas.X,
msi.ViewportOrigin.Y * msi.AspectRatio + ViewportHeight * relativeToCanvas.Y);
}


private Point DeepZoomToCanvas(MultiScaleImage msi, Point relativeInsideDeepZoom)
{
var ViewportHeight = msi.ViewportWidth * msi.AspectRatio * msi.ActualHeight / msi.ActualWidth;

var relativeToCanvas = new Point(
(relativeInsideDeepZoom.X - msi.ViewportOrigin.X) / msi.ViewportWidth,
(relativeInsideDeepZoom.Y - msi.ViewportOrigin.Y * msi.AspectRatio) / ViewportHeight);

return new Point(
relativeToCanvas.X * msi.ActualWidth,
relativeToCanvas.Y * msi.ActualHeight);
}

<强>2。在缩放和平移动画期间保持点同步。

基本思想是循环一个 0 秒长的动画,在缩放/平移的整个持续时间内不断更新您的点位置(如果我没记错的话是 1.5 秒)。该技术解释得很好here .在该博客中,您还可以找到针对您的特定问题的其他有用资源。

关于c# - 在 MultiScaleImage 上保持相对位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3947494/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com