编辑1 19/12
经过一番谷歌搜索后,我觉得可以更简洁地说明我的问题了。我想实现“缩放以适合”,其中以适当的比例因子显示比其父级更大的画布,但为用户提供了放大并查看完整尺寸图像的能力(使用滚动查看器)。我最初的实现并没有保持图像的长宽比,而是独立地对其进行处理,然后尝试使用一个滑块来管理两者。
我偶然发现this tutorial,制作了一个可滚动和可缩放的图像查看器,提供了“缩放以适合”的效果。之后,我将代码更改为以下代码。
if (CanvasWidth > CanvasHeight)
{
ScaleX = (Math.Floor(_scrollViewer.ViewportWidth + 0.5)) / ((double)CanvasWidth);
ScaleY = ScaleX;
if (_scrollViewer.Height < (CanvasHeight * ScaleY) )
{
ScaleX = ( _scrollViewer.Height) / (CanvasHeight);
ScaleY = ScaleX;
}
}
else
{
ScaleX = (Math.Floor(_scrollViewer.ViewportHeight + 0.5)) / ((double)CanvasHeight);
ScaleY = ScaleX;
if (_scrollViewer.Width < ( CanvasWidth * ScaleX) )
{
ScaleX = ((double)_scrollViewer.Width) / ((double)CanvasWidth);
ScaleY = ScaleX;
}
}
此更改似乎可以很好地起作用,但是我想知道是否有人可以向我解释如何计算长宽比,并且可以将图像正确缩放到父控件?
,即“内部if语句”的重要意义是什么,以及如何确保X和Y都相应地缩放。
原始问题
我正在画布上动态生成内容(有效地创建了一个图像地图,画布上的每个孩子都可以单击),其中内容的总宽度/高度通常大于其父对象的大小。在这种情况下,我应用 ScalerTransform 将图像缩放到合适的大小,以便在父控件中完全可见。
<Canvas.LayoutTransform>
<ScaleTransform ScaleX="{Binding ScaleX,RelativeSource={RelativeSource
TemplatedParent}}" ScaleY="{Binding ScaleY,RelativeSource={RelativeSource
TemplatedParent}}" />
</Canvas.LayoutTransform>
“画布”上的每个子元素都有固定的宽度/高度,这意味着我可以计算出所需的内容大小。
我通过执行类似的操作来计算初始X / Y比例因子。
ScaleX = ActualCanvasWidth / DesiredCanvasWidth;
ScaleY = ActualCanvasHeight / DesiredCanvasHeight;
这可以按预期工作,并且可以使画布很好地适合父容器。
我的问题是我想让用户能够缩放和平移图像。为此,我将Canvas包装在ScrollViewer中并添加了Slider。
<ScrollViewer Grid.Row="0" HorizontalScrollBarVisibility="Auto" x:Name="PART_ScrollViewer" VerticalScrollBarVisibility="Auto">
<Canvas x:Name="PART_MiniMapCanvas">
<Canvas.LayoutTransform>
<ScaleTransform ScaleX="{Binding ScaleX,RelativeSource={RelativeSource TemplatedParent}}"
ScaleY="{Binding ScaleY,RelativeSource={RelativeSource TemplatedParent}}" />
</Canvas.LayoutTransform>
</Canvas></ScrollViewer>
<Slider TickFrequency="1" IsSnapToTickEnabled="True" Grid.Row="0" Grid.Column="0" Minimum="1" Maximum="200" Value="{Binding ScaledPercent,RelativeSource={RelativeSource TemplatedParent}}" x:Name="sliderPercent" MinWidth="100px" />
UI使用一个滑块控制缩放,其值绑定到名为 ScaledPercent 的属性。滑块的初始值是这样计算的
double scaledArea = (DesiredCanvasWidth * ScaleX) * (DesiredCanvasHeight* ScaleY);
double desiredArea = DesiredCanvasWidth * DesiredCanvasHeight;
double scaledPercent = scaledArea/desiredArea;
据我了解,我可以执行此计算来查找整个画布的缩放比例,而不只是画布X / Y的比例因子。
您可以see here进行操作,画布及其父级的高度大约为160 * 200,所需的内容大小大约为300 * 320,相当于48000/96000,这是我使用了50%的位置通过滑块。
如果用户决定放大并将滑块的值更改为51,则将这个新的“缩放百分比”值转换为适用于画布的ScaleX / Y值。这是在依赖项属性回调中执行的
private static void OnScaledPercentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is MiniMap map)
{
int newPercent = (int)e.NewValue;
int oldPercent = (int)e.OldValue;
int diff = newPercent - oldPercent;
double oldWidth = map.CanvasWidth * map.ScaleX;
double oldHeight = map.CanvasHeight * map.ScaleY;
double scale = (diff > 0 ? (100 + diff) : (100 - Math.Abs(diff))) / 100d;
double newHeight = scale * oldHeight;
double newWidth = scale * oldWidth;
map.ScaleX = newWidth / map.CanvasWidth;
map.ScaleY = newHeight / map.CanvasHeight;
}
}
如您所见,我有效地将旧图像的宽度/高度缩放+/- 1%,然后计算新的缩放X / Y值。 see here似乎可以正常工作,但是如果您连续放大/缩小画布会变得很小,则无法显示。我认为这是因为我每次都在计算一个新的宽度/高度,并且最终会将其舍入为0。
很显然,我的实现过于复杂,错误且错误。如果有人可以帮助我或建议我如何实现所需的功能,我将不胜感激。