• 图片预览Image、加载、放缩、拖动


    Image属性Stretch

    Stretch 效果 备注
    None 图片原始大小 图片从原点(左上角)开始展示
    Fill 图片填满控件 图片不成比例
    Uniform 图片成比例尽可能填满控件 控件上下或者左右两侧可能有空白
    UniformToFill 图片成比例填满控件 图片的右下两侧有可能被裁剪

    XAML

    <UserControl.Resources>
      <Storyboard x:Key="MsgShowStory" Storyboard.TargetName="msgBorder">
          <DoubleAnimation From="1" To="0" Duration="0:0:1.5" Storyboard.TargetProperty="Opacity"/>
          <ObjectAnimationUsingKeyFrames  Storyboard.TargetProperty="Visibility" Duration="0:0:4">
              <ObjectAnimationUsingKeyFrames.KeyFrames>
                  <DiscreteObjectKeyFrame KeyTime="0:0:0" >
                      <DiscreteObjectKeyFrame.Value>
                          <Visibility>Visible</Visibility>
                      </DiscreteObjectKeyFrame.Value>
                  </DiscreteObjectKeyFrame>
                  <DiscreteObjectKeyFrame KeyTime="0:0:1.5" >
                      <DiscreteObjectKeyFrame.Value>
                          <Visibility>Collapsed</Visibility>
                      </DiscreteObjectKeyFrame.Value>
                  </DiscreteObjectKeyFrame>
              </ObjectAnimationUsingKeyFrames.KeyFrames>
          </ObjectAnimationUsingKeyFrames>
      </Storyboard>
    </UserControl.Resources>
    <Grid ClipToBounds="True" MouseWheel="Grid_MouseWheel" SizeChanged="Grid_SizeChanged" x:Name="gridDrawBoard" MouseLeave="GridMain_MouseLeave">
      <Grid x:Name="gridCanvas"
            Width="{Binding ElementName=image,Path=ActualWidth}"
            Height="{Binding ElementName=image,Path=ActualHeight}"
            HorizontalAlignment="Left" VerticalAlignment="Top">
          <Image x:Name="image" Stretch="Uniform" 
                 MouseLeftButtonDown="Image_MouseLeftButtonDown" MouseLeftButtonUp="Image_MouseLeftButtonUp" MouseMove="Image_MouseMove"/>
      </Grid>
      <Border x:Name="msgBorder" Width="100" Height="62" Background="WhiteSmoke" CornerRadius="5" Opacity="1" IsHitTestVisible="False" Visibility="Collapsed">
          <TextBlock x:Name="msgTextBlock" Text="100%" Foreground="Gray" FontWeight="Bold" FontSize="22" HorizontalAlignment="Center" VerticalAlignment="Center"/>
      </Border>
    </Grid>
    

    cs

    using System;
    using System.IO;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Input;
    using System.Windows.Media.Animation;
    using System.Windows.Media.Imaging;
    public partial class UC_ImageDisplay : UserControl
    {
      /// <summary>
      /// 原图大小
      /// </summary>
      private Size _imageSize;
      /// <summary>
      /// 界面大小
      /// </summary>
      private Size _ucSize;
      /// <summary>
      /// 最小缩放比例,不小于Mini(原始尺寸,当前容器)*50%
      /// </summary>
      private double _minScale;
      /// <summary>
      /// 最大缩放比例
      /// </summary>
      private double _maxScale;
    
      /// <summary>
      /// 初始默认缩放比
      /// </summary>
      private double _defaultScale;
      /// <summary>
      /// 画布相对于原图缩放比例
      /// </summary>
      private double _zoomScale;
    
      /// <summary>
      /// 鼠标滚动一次(120)代表的缩放大小
      /// </summary>
      private const double _scrollValue = 0.2;
      /// <summary>
      /// 是否开始拖动鼠标
      /// </summary>
      private bool _enableMove;
      /// <summary>
      /// 鼠标拖动的起点
      /// </summary>
      private Point _ptStart;
      /// <summary>
      /// 鼠标起点时的边距
      /// </summary>
      private Point _ptMargin;
    
      public UC_ImageDisplay()
      {
          InitializeComponent();
      }
    
      private void UserControl_Unloaded(object sender, RoutedEventArgs e)
      {
          // 释放资源
          BindingOperations.ClearBinding(image, System.Windows.Controls.Image.SourceProperty);
      }
    
      // 图片拖动
      // 图片居中
      // 图片加载
    }
    
    

    图片拖动

    private void Grid_MouseWheel(object sender, MouseWheelEventArgs e)
    {
        //计算新的缩放比
        var zoomScale = Math.Min(Math.Max((_zoomScale + _scrollValue * e.Delta / 120), _minScale), _maxScale);
        //新的缩放比跟旧的一样的话就不再浪费资源进行处理了
        if (_zoomScale == zoomScale) return;
    
        Point ptUI = e.GetPosition(this);//获取鼠标点相对于UI界面的坐标
        Point ptMap = e.GetPosition(gridCanvas);//获取鼠标点相对于缩放前画布的坐标
        Point ptImage = new Point(ptMap.X / _zoomScale, ptMap.Y / _zoomScale);//获取鼠标点相对于原图的坐标
        Point ptMapNew = new Point(ptImage.X * zoomScale, ptImage.Y * zoomScale);//计算鼠标点相对于缩放后画布的坐标
    
        Console.WriteLine($"=============================");
        Console.WriteLine($"图像大小是:长:{gridCanvas.Width / _zoomScale},宽:{gridCanvas.Height / _zoomScale}");
        Console.WriteLine($"Map缩放前大小是:长:{gridCanvas.Width },宽:{gridCanvas.Height}");
        Console.WriteLine($"Map缩放后大小是:长:{gridCanvas.Width * zoomScale / _zoomScale},宽:{gridCanvas.Height * zoomScale / _zoomScale}");
        Console.WriteLine($"缩放点的UI坐标是:X:{ptUI.X },Y:{ptUI.Y }");
        Console.WriteLine($"缩放点的真实坐标是:X:{ptImage.X},Y:{ptImage.Y }");
        Console.WriteLine($"缩放点的在Map上的原坐标是:X:{ptMap.X },Y:{ptMap.Y }");
        Console.WriteLine($"缩放点的在Map上缩放后的坐标是,X:{ptMapNew.X },Y:{ptMapNew.Y }");
        Console.WriteLine($"MapMargin,X:{gridCanvas.Margin.Left },Y:{gridCanvas.Margin.Top }");
    
        //计算缩放后画布的偏移量
        if (zoomScale == _defaultScale)
        {
            double left = (_ucSize.Width - _imageSize.Width * zoomScale) / 2;
            double top = (_ucSize.Height - _imageSize.Height * zoomScale) / 2;
            Console.WriteLine($"Margin after,X:{left},Y:{top}");
            gridCanvas.Margin = new Thickness(left, top, 0, 0);
        }
        else
        {
            var left = (ptMapNew.X - ptMap.X) * (-1);
            var top = (ptMapNew.Y - ptMap.Y) * (-1);
            Console.WriteLine($"Margin after,X:{left},Y:{top}");
    
            // 画布大小
            var width = gridCanvas.Width * zoomScale / _zoomScale;
            var height = gridCanvas.Height * zoomScale / _zoomScale;
            if (zoomScale > _zoomScale) // 放大
            {
                // 鼠标位置相对不动
                left += gridCanvas.Margin.Left;
                top += gridCanvas.Margin.Top;
                if (width <= gridDrawBoard.ActualWidth)
                {
                    left = (gridDrawBoard.ActualWidth - width) / 2;
                }
                if (height <= gridDrawBoard.ActualHeight)
                {
                    top = (gridDrawBoard.ActualHeight - height) / 2;
                }
            }
            else
            {   
                // 缩小时新边距过大
                if (left + width >= gridDrawBoard.ActualWidth)
                {
                    left = (gridDrawBoard.ActualWidth - width) / 2;
                }
                if (top + height >= gridDrawBoard.ActualHeight)
                {
                    top = (gridDrawBoard.ActualHeight - height) / 2;
                }
            }
            gridCanvas.Margin = new Thickness(left, top, 0, 0);
        }
        SetImageZoomScale(zoomScale);
    }
    
    private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _enableMove = true;
        //获取鼠标点相对于UI界面的坐标
        _ptStart = e.GetPosition(this);
        _ptMargin.X = gridCanvas.Margin.Left;
        _ptMargin.Y = gridCanvas.Margin.Top;
    }
    private void Image_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        _enableMove = false;
    }
    private void GridMain_MouseLeave(object sender, MouseEventArgs e)
    {
        _enableMove = false;
    }
    
    private void Image_MouseMove(object sender, MouseEventArgs e)
    {
        if (_enableMove)
        {
            //计算新的缩放比
            var zoomScale = Math.Min(Math.Max(_zoomScale, _minScale), _maxScale);
            if (IsEqual(zoomScale, _defaultScale))
            {
                return;
            }
            Point ptUI = e.GetPosition(this);//获取鼠标点相对于UI界面的坐标
            Point ptMap = e.GetPosition(gridCanvas);//获取鼠标点相对于缩放前画布的坐标
            Point ptImage = new Point(ptMap.X / _zoomScale, ptMap.Y / _zoomScale);//获取鼠标点相对于原图的坐标
            Point ptMapNew = new Point(ptImage.X * zoomScale, ptImage.Y * zoomScale);//计算鼠标点相对于缩放后画布的坐标
    
            Console.WriteLine($"=============================");
            Console.WriteLine($"图像大小是:长:{gridCanvas.Width / _zoomScale},宽:{gridCanvas.Height / _zoomScale}  画板:{gridDrawBoard.ActualWidth} X {gridDrawBoard.ActualHeight}");
            Console.WriteLine($"Map缩放前大小是:长:{gridCanvas.Width },宽:{gridCanvas.Height}");
            Console.WriteLine($"Map缩放后大小是:长:{gridCanvas.Width * zoomScale / _zoomScale},宽:{gridCanvas.Height * zoomScale / _zoomScale}");
            Console.WriteLine($"缩放点的UI坐标是:X:{ptUI.X },Y:{ptUI.Y }");
            Console.WriteLine($"缩放点的真实坐标是:X:{ptImage.X},Y:{ptImage.Y }");
            Console.WriteLine($"缩放点的在Map上的原坐标是:X:{ptMap.X },Y:{ptMap.Y }");
            Console.WriteLine($"缩放点的在Map上缩放后的坐标是,X:{ptMapNew.X },Y:{ptMapNew.Y }");
            Console.WriteLine($"MapMargin,X:{gridCanvas.Margin.Left },Y:{gridCanvas.Margin.Top }");
    
            var xOffset = _ptMargin.X + (ptUI.X - _ptStart.X);
            var yOffset = _ptMargin.Y + (ptUI.Y - _ptStart.Y);
    
            SetImageMargin(xOffset, yOffset);
        }
    }
    
    /// <summary>
    /// 鼠标拖动时画布相对界面的偏移量
    /// </summary>
    private void SetImageMargin(double left, double top)
    {
        var blankWidth = gridDrawBoard.ActualWidth - gridCanvas.Width;
        var blankHeight = gridDrawBoard.ActualHeight - gridCanvas.Height;
    
        // 如果留有空白
        if (blankWidth >= 0)
        {
            left = blankWidth / 2;
        }
        else
        {
            // 边界判断 
            if (left >= 0)
            {
                left = 0;
            }
            else if (left <= blankWidth)
            {
                left = blankWidth;
            }
        }
        if (blankHeight >= 0)
        {
            top = blankHeight / 2;
        }
        else
        {
            if (top >= 0)
            {
                top = 0;
            }
            else if (top <= blankHeight)
            {
                top = blankHeight;
            }
        }
        
        this.Dispatcher.BeginInvoke(new Action(() =>
        {
            gridCanvas.Margin = new Thickness(left, top, 0, 0);
        }));
    } 
    

    图片居中

    private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
    {
       InitZoomScaleImageDispaly();
    }
    private void InitZoomScaleImageDispaly()
    {
       _ucSize = base.RenderSize;
       CalculateZoomScale(_imageSize, _ucSize);
       _defaultScale = _zoomScale;
       // 居中显示
       double left = (_ucSize.Width - _imageSize.Width * _zoomScale) / 2;
       double top = (_ucSize.Height - _imageSize.Height * _zoomScale) / 2;
       gridCanvas.Margin = new Thickness(left, top, 0, 0);
    }
    /// <summary>
    /// 设置默认的缩放比、最小缩放比、最大缩放比
    /// </summary>
    /// <param name="imageSize">图像大小</param>
    /// <param name="uiSize">待显示的界面大小</param>
    /// <returns></returns>
    private void CalculateZoomScale(Size imageSize, Size uiSize)
    {
       if (imageSize.Width == 0 || imageSize.Height == 0) return;
       if (uiSize.Width == 0 || uiSize.Height == 0) return;
    
       //取最大的压缩比例
       var zoomScale = Math.Min(uiSize.Width / imageSize.Width, uiSize.Height / imageSize.Height);
    
       //图片尺寸大于容器
       if (zoomScale < 1)
       {
           if (zoomScale < 0.5)
           {
               //极大
               _minScale = zoomScale;
               _maxScale = Math.Floor(1 / zoomScale);
           }
           else
           {
               _minScale = zoomScale;
               _maxScale = Math.Ceiling(2 / zoomScale);
           }
       }
       //图片尺寸小于容器
       else
       {
           if (zoomScale > 8)
           {
               //极小
               _minScale = 1;
               _maxScale = Math.Floor(0.5 * zoomScale);
               zoomScale = _maxScale;
           }
           else if (zoomScale > 4)
           {
               //较小
               _minScale = 1;
               _maxScale = Math.Floor(0.75 * zoomScale);
               zoomScale = _maxScale;
           }
           else
           {
               _minScale = 1;
               _maxScale = Math.Ceiling(zoomScale);
               zoomScale = 1;
           }
       }
    
       SetImageZoomScale(zoomScale);
    }
    /// <summary>
    /// 画布相对于原图缩放比例
    /// </summary>
    private void SetImageZoomScale(double zoomScale)
    {
        if (zoomScale <= 0)
            return;
        _zoomScale = zoomScale;
        this.Dispatcher.BeginInvoke(new Action(() =>
        {
            //计算缩放后图片的大小
            image.Width = _imageSize.Width * zoomScale;
            image.Height = _imageSize.Height * zoomScale;
            msgTextBlock.Text = Math.Round(zoomScale * 100) + "%";
            Storyboard storyboard = FindResource("MsgShowStory") as Storyboard;
            storyboard.Begin();
        }));
    }
    

    Image绑定图片

    /// <summary>
      /// 从字节数组加载图片
      /// </summary>
      /// <param name="bytes"></param>
      public void LoadLayer(byte[] bytes)
      {
          BitmapImage bitmap = new BitmapImage();
          bitmap.BeginInit();
          bitmap.CacheOption = BitmapCacheOption.OnLoad;
          bitmap.CreateOptions = BitmapCreateOptions.DelayCreation;
          using (var ms = new MemoryStream(bytes))
          {
              bitmap.StreamSource = ms;
              bitmap.EndInit();
              bitmap.Freeze();
          }
          LoadLayer(bitmap);
      }
    
      /// <summary>
      /// 加载底图(Uniform缩小或最佳比例放大)
      /// </summary>
      /// <param name="bmp"></param>
      /// <param name="mouseOperateType"></param>
      public void LoadLayer(BitmapImage bmp)
      {
          BindingOperations.ClearBinding(image, Image.SourceProperty);
          image.Source = bmp;
          _imageSize = new Size(bmp.PixelWidth, bmp.PixelHeight);
          InitZoomScaleImageDispaly();
      }
    

    IsEqual 浮点数double相等性比较

    Uri路径引用

    XAML

    <Image x:Name="Image1" Source="pack://application:,,,/Image/nopicture.jpg"/>
    <Image x:Name="Image2" Source="pack://application:,,,/ImageLibrary;component/Image/nopicture.jpg"/>
    

    cs

    Image1.Source = new BitmapImage(new Uri("pack://application:,,,/Image/nopicture.jpg"));
    Image2.Source = new BirmapImage(new Uri(“pack://application:,,,/ImageLibrary;component/Image/nopicture.jpg”));
    Image2.Source = new BitmapImage(new Uri(“ImageLibiary;component/iImage/nopicture.jpg”, UriKind.Relavite));
    
  • 相关阅读:
    20155311《信息安全系统设计基础》课程总结
    20155311《信息安全系统设计基础》第14周学习总结
    20155311《信息安全系统设计基础》第十三周学习总结
    2017-2018-1 《信息安全系统设计基础》实验五 通信协议设计
    补交课下测试(ch12并发编程) 08.第八周
    2017-2018-1 20155311 实验四 外设驱动程序设计
    2017-2018-1 学号20155311 《信息安全系统设计基础》第11周学习总结
    PWD的编译及调试
    2017-2018-1 学号20155311 《信息安全系统设计基础》第9周学习总结
    2017-2018-1 20155311 实验三 实时系统
  • 原文地址:https://www.cnblogs.com/wesson2019-blog/p/14714008.html
Copyright © 2020-2023  润新知