在执行缩放手势时替换ScrollViewer中的图像

Vit*_*aly 5 windows-8 winrt-xaml windows-store-apps

我正在创建一个照片查看应用程序,我想实现缩放图片.我创建了一个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; }
    }
Run Code Online (Sandbox Code Playgroud)

这是我的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>
Run Code Online (Sandbox Code Playgroud)

这是我的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);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

正如我已经提到的,此代码的问题在于手势被中断并且新图像未调整大小/滚动到正确位置,用户体验不是无缝的.感谢您提供有关如何解决此问题的任何建议.

Jer*_*xon 0

我不会为您编写这段代码,因为它太多了,但步骤如下:

  1. 图像需要将 ScaleTransform 应用于其 RenderTransform 属性。当用户捏合或拉伸时,您将使用它来使其“缩放”。
  2. 使用 Manipulation 事件检测捏合手势;如果可以帮助您减少一些代码,您甚至可以只过滤捏合手势。这些事件将是最可靠的。
  3. Manipulation 事件将返回发生了多少收缩或拉伸,这需要对应于您对数字 1 中的图像 ScaleTransform 应用的缩放程度。
  4. 在代码隐藏中,您可以创建一个指向服务器并从服务器加载图像的 BitmapImage。加载后,您可以替换用户捏合的图像的来源。这对用户来说几乎是无缝的,除非高分辨率图像是数兆字节。不要那样做。

请注意,我的步骤不包括 ScrollViewer。ScrollViewer 当然可以包裹图像,但工作本身是作为图像本身的一部分完成的。

我还可能会向您指出MultiScaleImage您可能想要从中窃取一些逻辑的控件,以便做到最好:http://msdn.microsoft.com/en-us/library/system.windows.controls.multiscaleimage%28v=对比95%29.aspx

还有一件事。使用 DeepZoom 可以轻松实现这一点。由于它在 XAML 中尚不可用,因此并不意味着您不能利用 WebView 来完成此任务。它将为您提供一个预构建的、可扩展的(且免费)解决方案。但选择权在你。