2013-01-24 32 views
5

Tôi đang tạo ứng dụng xem ảnh và tôi muốn triển khai phóng to ảnh. Tôi tạo ra một ScrollViewer và đặt một hình ảnh ở đó. Tất cả đều hoạt động ra khỏi hộp. Tôi có thể làm một cử chỉ zoom và nó phóng to hình ảnh. Bây giờ, điều tiếp theo tôi muốn thực hiện là tải phiên bản độ phân giải cao của hình ảnh khi cử chỉ thu phóng bắt đầu và tự động hoán đổi bitmap trong điều khiển Hình ảnh khi được tải. Tôi muốn nó xảy ra liền mạch, để người dùng có thể tiếp tục cử chỉ và tiếp tục phóng to và xem hình ảnh chi tiết hơn. Cách tiếp cận tốt nhất để thực hiện điều này là gì? Đây là mã mà tôi hiện có. Vấn đề với mã của tôi là khi Image.Source được thay thế thì cử chỉ của tôi bị gián đoạn và ảnh được đặt lại về kích thước ban đầu. Thay đổi ScrollViewer ZoomFactor không giúp ích khi nó có vẻ như được thiết lập lại khi hình ảnh đang được thay thế. Tôi có một DataModel với thuộc tính Hình ảnh ban đầu trả về giá trị null nhưng bắt đầu tải ảnh từ 'tệp' ở chế độ có độ phân giải thấp và gọi OnPropertyChanged ("Hình ảnh") khi tải xong. Gọi LoadFullImage() tải phiên bản có độ phân giải đầy đủ và gọi OnPropertyChanged ("Hình ảnh") khi hoàn tất.Thay thế hình ảnh trong ScrollViewer trong khi thực hiện thao tác thu phóng

Dưới đây là chiết xuất từ ​​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; } 
    } 

Đây là MainPage.xaml tôi:

<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> 

Đây là MainPage.xaml.cs tôi:

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); 
      } 
     } 
    } 

Như Tôi đã đề cập, vấn đề với mã này là các cử chỉ bị gián đoạn và một hình ảnh mới không được thay đổi kích thước/cuộn đến đúng vị trí, trải nghiệm người dùng không liền mạch. Cảm ơn mọi đề xuất về cách giải quyết vấn đề này.

Trả lời

0

Tôi sẽ không viết mã này cho bạn vì nó sẽ là quá nhiều, nhưng ở đây là các bước:

  1. Các hình ảnh cần phải có một ScaleTransform áp dụng cho bất động sản RenderTransform của nó. Bạn sẽ sử dụng điều này để làm cho nó 'thu phóng' khi người dùng đang véo hoặc kéo dài.
  2. Phát hiện cử chỉ chụm bằng các sự kiện Thao tác; bạn thậm chí có thể lọc chỉ cử chỉ chụm nếu nó giúp bạn giảm bớt một số mã. Những sự kiện này sẽ đáng tin cậy nhất.
  3. Sự kiện thao tác sẽ trả lại số lượng pinch hoặc giãn ra, điều này cần tương ứng với mức độ bạn áp dụng cho ScaleTransform của hình ảnh ở số 1.
  4. Trong mã sau bạn có thể tạo BitmapImage trỏ đến và tải hình ảnh từ máy chủ. Sau khi đã tải xong, bạn có thể thay thế nguồn của hình ảnh mà người dùng đang ghim. Điều này sẽ gần như liền mạch với người dùng trừ khi hình ảnh có độ phân giải cao là nhiều megabyte. Đừng làm thế.

Xin lưu ý rằng các bước của tôi không bao gồm ScrollViewer. Một ScrollViewer chắc chắn có thể bọc hình ảnh, nhưng bản thân công việc được thực hiện như là một phần của chính Image đó.

Tôi cũng có thể chỉ cho bạn đến MultiScaleImage điều khiển mà bạn có thể muốn ăn cắp một số logic từ để làm được điều tốt nhất này: http://msdn.microsoft.com/en-us/library/system.windows.controls.multiscaleimage%28v=vs.95%29.aspx

Có một điều nữa. Điều này có thể được thực hiện khá dễ dàng với DeepZoom. Vì nó chưa có sẵn trong XAML, nó không có nghĩa là bạn không thể tận dụng một WebView để thực hiện điều này. Nó sẽ cung cấp cho bạn giải pháp được xây dựng sẵn, có khả năng mở rộng (và miễn phí). Nhưng sự lựa chọn là của bạn.

+0

Jerry, tôi nghĩ rằng cách tiếp cận với ScaleTransform là cần thiết khi ScrollViewer không hỗ trợ cử chỉ thu phóng. Hiện tại nó hoạt động hoàn hảo với một hình ảnh duy nhất - tôi có thể phóng to rất mượt mà. Ngoài ra ScrollViewer của tôi được chứa trong các điều khiển FlipView và cử chỉ từ cả hai ScrollViewer và FlipView điều khiển làm việc tuyệt vời với nhau: tôi có thể lật hình ảnh và phóng to khi cần thiết. Bạn đang nói rằng nó không thể chuyển đổi hình ảnh liền mạch trong ScrollViewer? – Vitaly

0

Ai cũng nhớ chủ đề này? =) ok,
Tôi đã triển khai 'Thay thế hình ảnh trong khi phóng to' trên my app.
Như @Vitary đã đề cập ở trên, nếu kích thước của 'nội dung' được thay đổi, tỷ lệ thu phóng cài đặt scrollviewer và bù X/Y.
Để tránh nó, ứng dụng của tôi XAML sử dụng cấu trúc sau:

<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> 

Bằng cách giữ kích thước của viewbox như tương tự, bạn có thể tránh được thiết lập lại của người xem di chuyển. Triển khai của tôi là ...

  1. Người dùng chọn mục lật. Tại trình tự này, mã nguồn viewource đặt w/h của hình ảnh gốc thành thành viên xem nguồn. Thành viên này được liên kết với w/h của hộp xem.
  2. Giải mã có độ phân giải thấp. sau đó thiết lập để kiểm soát hình ảnh bằng cách ràng buộc. Như bạn biết, chế độ xem có thể kéo dài nội dung để vừa với kích thước của hộp xem tự động.
  3. Khi người dùng thực hiện thao tác thu phóng, codebehind thông báo cho ViewModel. ViewModel bắt đầu giải mã gốc, sau đó đặt hình ảnh thành điều khiển hình ảnh bằng cách liên kết. Trong trình tự này, trình xem cuộn có thể giữ tỷ lệ bù trừ và thu phóng. Bởi vì, kích thước của viewbox không thay đổi. Việc chuyển đổi từ độ phân giải thấp đến độ phân giải ban đầu là trơn tru và không bị trục trặc.
Các vấn đề liên quan