我正在创建一个照片查看应用程序,我想实现缩放图片。我创建了一个ScrollViewer并在那里放置了一个Image。这一切都是开箱即用的。我可以做一个缩放手势,它放大图片。现在,我想要实现的下一件事是在缩放手势开始时加载图片的高分辨率版本,并在加载时动态交换Image控件中的位图。我希望它无缝地发生,以便用户可以继续手势并继续放大并查看更详细的图片。 实现这一目标的最佳方法是什么? 这是我目前拥有的代码。我的代码的问题是,当替换Image.Source时,我的手势被中断,照片被重置为原始大小。更改ScrollViewer ZoomFactor没有帮助,因为它似乎在更换图像时被重置。 我有一个带有Image属性的DataModel,它最初返回null但是在低分辨率模式下从'file'开始加载图片,并在加载完成时调用OnPropertyChanged(“Image”)。调用LoadFullImage()加载完整分辨率版本并在完成时调用OnPropertyChanged(“Image”)。
以下是DataModel.cs的摘录:
public async Task LoadFullImage()
{
loadFullImageTask = UpdateImage(0);
await loadFullImageTask;
}
public ImageSource Image
{
get
{
if (fullImage != null)
{
return fullImage;
}
else if (image != null)
{
return image;
}
else
{
Task loadImageTask = UpdateImage(768);
return null;
}
}
}
public bool FullImageLoading
{
get { return (this.loadFullImageTask != null) && (!this.loadFullImageTask.IsCompleted); }
}
public bool FullImageLoaded
{
get { return this.fullImage != null; }
}
这是我的MainPage.xaml:
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<ScrollViewer x:Name="imageViewer" HorizontalAlignment="Stretch" HorizontalScrollBarVisibility="Visible" VerticalAlignment="Stretch" MinZoomFactor="1" ZoomMode="Enabled" ViewChanged="imageViewer_ViewChanged">
<Image x:Name="image" Margin="0,0,0,0" Stretch="Uniform" Source="{Binding Image}" />
</ScrollViewer>
</Grid>
这是我的MainPage.xaml.cs:
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
FileOpenPicker filePicker = new FileOpenPicker();
filePicker.SuggestedStartLocation = PickerLocationId.ComputerFolder;
filePicker.FileTypeFilter.Add(".jpg");
StorageFile file = await filePicker.PickSingleFileAsync();
data = new DataModel(file);
imageViewer.DataContext = data;
}
private async void imageViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
ScrollViewer imageViewer = (ScrollViewer)sender;
if (imageViewer.ZoomFactor > 1)
{
if (!data.FullImageLoaded && (!data.FullImageLoading))
{
int oldHeight = ((BitmapImage)data.Image).PixelHeight;
int oldWidth = ((BitmapImage)data.Image).PixelWidth;
double oldHOffset = imageViewer.HorizontalOffset;
double oldVOffset = imageViewer.VerticalOffset;
await data.LoadFullImage();
int newHeight = ((BitmapImage)data.Image).PixelHeight;
int newWidth = ((BitmapImage)data.Image).PixelWidth;
float ratio = (float)oldHeight / (float)newHeight;
imageViewer.MaxZoomFactor = imageViewer.MaxZoomFactor * ratio;
imageViewer.MinZoomFactor = imageViewer.MinZoomFactor * ratio;
imageViewer.ZoomToFactor(imageViewer.ZoomFactor * ratio);
//imageViewer.ScrollToHorizontalOffset(oldHOffset / ratio);
//imageViewer.ScrollToVerticalOffset(oldVOffset / ratio);
}
}
}
正如我已经提到的,此代码的问题在于手势被中断并且新图像未调整大小/滚动到正确位置,用户体验不是无缝的。 感谢您提供有关如何解决此问题的任何建议。
答案 0 :(得分:0)
我不打算为你编写这段代码,因为它太多了,但是这里是步骤:
请注意,我的步骤不包括ScrollViewer。 ScrollViewer当然可以包装图像,但工作本身是作为Image本身的一部分完成的。
我可能还会指向MultiScaleImage
控件,你可能想要窃取一些逻辑以便做到最好:http://msdn.microsoft.com/en-us/library/system.windows.controls.multiscaleimage%28v=vs.95%29.aspx
还有一件事。使用DeepZoom可以很容易地完成此操作。由于它尚未在XAML中提供,因此并不意味着您无法利用WebView来实现此目的。它将为您提供预先构建的,疯狂可扩展(和免费)的解决方案。但选择权在你手中。
答案 1 :(得分:0)
有人记得这个帖子吗? =)好的,
我已经实现了在缩放期间更换图像&#39;在my app上
正如上面提到的@Vitary,如果&#39;内容的大小&#39;更改后,滚动查看器重置缩放比率和X / Y偏移
为避免这种情况,我的应用程序xaml使用以下结构:
<FlipView>
<DataTemplate>
<ScrollViewer>
<ViewBox> <-- This size is same with original image width/height. No change during zoom in/out.
<Image/> <-- This size is vary.
</ViewBox>
</ScrollViewer>
</DataTemplate>
</FlipView>
通过将视图框的大小保持不变,可以避免重置滚动查看器。 我的实施是......