Windows 8 系列 -- 仿新浪微博图片放大功能 --随笔

定义图片放大的Xaml文件:

 

View Code
<UserControl
    x:Class="Win8_ScorllViewer.LodingImage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Win8_ScorllViewer"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">

    <Grid x:Name="LayoutRoot"   Background="Transparent"  PointerPressed="LayoutRoot_PointerPressed_1"  >
        <Grid.RowDefinitions>
            <RowDefinition  Height="*"></RowDefinition>
            <RowDefinition Height="160"></RowDefinition>
        </Grid.RowDefinitions>
        <Rectangle x:Name="rectShadow" Grid.RowSpan="2"></Rectangle>
        <Canvas Grid.RowSpan="2">
            <!-- 注意 Stretch="Fill"  -->
            <Image 
                x:Name="img" 
                PointerMoved="img_PointerMoved_1" 
                PointerReleased="img_PointerReleased_1" 
                PointerPressed="img_PointerPressed_1"  
                PointerEntered="img_PointerEntered_1" 
                PointerExited="img_PointerExited_1"  
                Stretch="Fill"   
                   >
            <Image.RenderTransform>
                <ScaleTransform x:Name="st" />
            </Image.RenderTransform>
        </Image>
        </Canvas>
        <StackPanel HorizontalAlignment="Center" Orientation="Vertical" VerticalAlignment="Center" Grid.Row="1">
            <StackPanel Margin="30" Orientation="Horizontal">
            <Rectangle x:Name="rectProcess" Width="180" Height="10"  RadiusX="3" RadiusY="3" >
                    <Rectangle.Fill>
                        <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
                            <GradientStop Color="#4682b4" Offset="0" />
                            <GradientStop Color="#4682b4" x:Name="blue1" Offset="0" />
                            <GradientStop Color="gray" x:Name="gray1" Offset="0" />
                            <GradientStop Color="gray" Offset="1" />
                        </LinearGradientBrush>
                        
                    </Rectangle.Fill>
                        <Rectangle.Resources>
                        <Storyboard x:Name="sbRect">
                            
                        </Storyboard>
                        
                    </Rectangle.Resources>

                </Rectangle>
            <TextBlock Margin="10 0 0 0"  Text="正在加载 85%" x:Name="TxtLoading" HorizontalAlignment="Center" Foreground="Black" VerticalAlignment="Center" />
            </StackPanel>
            <Rectangle Width="30" Height="30" Fill="Red" RadiusX="3" RadiusY="3" ></Rectangle>
        </StackPanel>
    </Grid>
</UserControl>

 

后台文件:

View Code
 public sealed partial class LodingImage : UserControl
    {


        /// <summary>
        /// 屏幕大小
        /// </summary>
        Rect bounds = Window.Current.Bounds;
        private string _uri = string.Empty;
        private Uri _baseUri = new Uri("ms-appx:///");
        BitmapImage bitmapImage;
        /// <summary>
        /// 是否可以移动
        /// </summary>
        private bool canMove = false;
        /// <summary>
        /// 鼠标/手指 移动前的坐标
        /// </summary>
        PointerPoint startPoint;
        /// <summary>
        /// 加载时图片默认Canvas.Left Canvas.Top坐标
        /// </summary>
        Point defaultPosition;
        /// <summary>
        /// 屏幕的中心位置
        /// </summary>
        Point defaultPoint;
        /// <summary>
        /// 当前移动位置和默认坐标的相差位移
        /// </summary>
        Point destancePoint = new Point(0, 0);
        /// <summary>
        /// 要显示的URI地址
        /// </summary>
        public string Uri
        {
            set
            {
                bitmapImage = new BitmapImage();
                img.Source = bitmapImage;
                bitmapImage.UriSource = new Uri(_baseUri, value);//测试用本地图片
                SetImageProperty();
                TxtLoading.Visibility = rectProcess.Visibility = Visibility.Visible;
                bitmapImage.DownloadProgress += bitmapImage_DownloadProgress;
                bitmapImage.ImageFailed += bitmapImage_ImageFailed;
                bitmapImage.ImageOpened += bitmapImage_ImageOpened;
            }
            get
            {
                return _uri;
            }
        }

        private double _scaleRate = 0.2;
        public double ScaleRate
        {
            get
            {
                return _scaleRate;
            }
            set
            {
                _scaleRate = value;
            }
        }

        public Image OriginalImage
        {
            set
            {

                img.Height = value.Height;
                img.Width = value.Width;
                img.Source = value.Source;
            }
            get
            {
                return img;
            }
        }
        public Stretch ImageStretch
        {
            get { return img.Stretch; }
            set { img.Stretch = value; }
        }


        public LodingImage()
        {
            this.InitializeComponent();
            this.Loaded += LodingImage_Loaded;
            this.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
        }
        public void Show()
        {
            this.Visibility = Windows.UI.Xaml.Visibility.Visible;
        }
        void LodingImage_Loaded(object sender, RoutedEventArgs e)
        {
            rectShadow.Width = bounds.Width;
            rectShadow.Height = bounds.Height;
            rectShadow.Fill = new SolidColorBrush(Colors.Gray);
            rectShadow.Opacity = 0.3;
        }

        void bitmapImage_DownloadProgress(object sender, DownloadProgressEventArgs e)
        {
            double moveRate = e.Progress * 1.0 / 100;
            gray1.Offset += moveRate;
            blue1.Offset += moveRate;
            TxtLoading.Text = string.Format("正在加载 {0}%", e.Progress);
        }

        void bitmapImage_ImageFailed(object sender, ExceptionRoutedEventArgs e)
        {
            TxtLoading.Text = string.Format("加载失败");
        }
        void bitmapImage_ImageOpened(object sender, RoutedEventArgs e)
        {
            TxtLoading.Visibility = rectProcess.Visibility = Visibility.Collapsed;
        }
        void ReLoad()
        {
            bitmapImage = new BitmapImage();
        }

        private void img_PointerEntered_1(object sender, PointerRoutedEventArgs e)
        {
            img.PointerWheelChanged += img_PointerWheelChanged;
        }

        void img_PointerWheelChanged(object sender, PointerRoutedEventArgs e)
        {
            var pointerPointer = e.GetCurrentPoint(img);
            //注意pointerPoint.Properties属性 提供我们想要的很多属性
            var delta = pointerPointer.Properties.MouseWheelDelta;

            double rate = ScaleRate;
            if (delta < 0)
            {
                rate = rate * -1;
            }

            if (st.ScaleX + rate <= 0.4)
            {
                return;
            }


            /*
             * 如果产生了相对位移的话即图片位置被移动过
             * 则处理缩放的大小和相对位移做运算
             * bug 当缩小时应该为下面的算法
             *     
             */
            if (rate < 0)
            {
                if (destancePoint.Y > 0)
                {
                    double dY = Math.Abs((rate * img.Height) / 2);
                    double moveTop = Convert.ToDouble(img.GetValue(Canvas.TopProperty));
                    if (dY >= Math.Abs(destancePoint.Y))
                    {
                        img.SetValue(Canvas.TopProperty, defaultPosition.Y);
                        destancePoint.Y = 0;
                    }
                    else
                    {
                        destancePoint.Y -= dY;
                        img.SetValue(Canvas.TopProperty, moveTop - dY);
                    }
                }
                else if (destancePoint.Y < 0)
                {
                    double dY = Math.Abs((rate * img.Height) / 2);
                    double moveTop = Convert.ToDouble(img.GetValue(Canvas.TopProperty));
                    if (dY >= Math.Abs(destancePoint.Y))
                    {
                        img.SetValue(Canvas.TopProperty, defaultPosition.Y);
                        destancePoint.Y = 0;
                    }
                    else
                    {
                        destancePoint.Y += dY;
                        img.SetValue(Canvas.TopProperty, moveTop + dY);
                    }
                }

                if (destancePoint.X > 0)
                {
                    double dX = Math.Abs((rate * img.Width) / 2);
                    double moveLeft = Convert.ToDouble(img.GetValue(Canvas.LeftProperty));
                    if (dX >= Math.Abs(destancePoint.X))
                    {
                        img.SetValue(Canvas.LeftProperty, defaultPosition.X);
                        destancePoint.X = 0;
                    }
                    else
                    {
                        destancePoint.X -= dX;
                        img.SetValue(Canvas.LeftProperty, moveLeft - dX);
                    }
                }
                else if (destancePoint.X < 0)
                {
                    double dX = Math.Abs((rate * img.Width) / 2);
                    double moveLeft = Convert.ToDouble(img.GetValue(Canvas.LeftProperty));
                    if (dX >= Math.Abs(destancePoint.X))
                    {
                        img.SetValue(Canvas.LeftProperty, defaultPosition.X);
                        destancePoint.X = 0;
                    }
                    else
                    {
                        destancePoint.X += dX;
                        img.SetValue(Canvas.LeftProperty, moveLeft + dX);
                    }
                }

            }
            else
            {
                    

            }
            st.ScaleY += rate;
            st.ScaleX += rate;

        }

        private void img_PointerExited_1(object sender, PointerRoutedEventArgs e)
        {
            img.PointerWheelChanged -= img_PointerWheelChanged;
        }

        private void LayoutRoot_PointerPressed_1(object sender, PointerRoutedEventArgs e)
        {
            this.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
        }

        private void img_PointerPressed_1(object sender, PointerRoutedEventArgs e)
        {
            FrameworkElement element = sender as FrameworkElement;
            canMove = true;
            if (element != null)
            {
                element.CapturePointer(e.Pointer);
            }
            startPoint = e.GetCurrentPoint(LayoutRoot);

            e.Handled = true;
        }

        private void img_PointerMoved_1(object sender, PointerRoutedEventArgs e)
        {
            if (canMove)
            {
                PointerPoint point = e.GetCurrentPoint(LayoutRoot);
                if (IsWidthOutBounds())
                {
                    double left = double.Parse(img.GetValue(Canvas.LeftProperty).ToString());
                    double moveToX = (point.Position.X - startPoint.Position.X) + left;
                    destancePoint.X = moveToX - defaultPoint.X + img.Width / 2;
                    double destanceX = Math.Abs(destancePoint.X);
                    if (destanceX <= (img.Width * st.ScaleX - bounds.Width) / 2)
                    {
                        img.SetValue(Canvas.LeftProperty, moveToX);
                    }
                }
                if (IsHeightOutBounds())
                {
                    double top = double.Parse(img.GetValue(Canvas.TopProperty).ToString());
                    double moveToY = (point.Position.Y - startPoint.Position.Y) + top;
                    destancePoint.Y = moveToY - defaultPoint.Y + img.Height /2;
                    double destanceY = Math.Abs(destancePoint.Y);
                    if (destanceY <= (img.Height * st.ScaleY - bounds.Height) / 2)
                    {
                        img.SetValue(Canvas.TopProperty, moveToY);
                    }

                }
                startPoint = e.GetCurrentPoint(LayoutRoot);
            }
        }

        private void img_PointerReleased_1(object sender, PointerRoutedEventArgs e)
        {
            FrameworkElement element = sender as FrameworkElement;
            element.ReleasePointerCapture(e.Pointer);
            canMove = false;

        }


        private void SetImageProperty()
        {
            st.ScaleX = 1.5;
            st.ScaleY = 1.5;
            st.CenterX = img.Width / 2;
            st.CenterY = img.Height / 2;
            double top = (bounds.Height - img.Height) / 2;
            double left = (bounds.Width - img.Width) / 2;
            defaultPosition = new Point(left, top);
            destancePoint = new Point(0, 0);
            defaultPoint = new Point(bounds.Width / 2, bounds.Height / 2);
            img.SetValue(Canvas.TopProperty, top);
            img.SetValue(Canvas.LeftProperty, left);
        }
        /// <summary>
        /// 判断是否超过纵向边界
        /// </summary>
        /// <returns></returns>
        private bool IsHeightOutBounds()
        {
            double rate = st.ScaleY;
            if ((rate * img.Height) > bounds.Height)
            {
                return true;
            }
            return false;
        }
        /// <summary>
        /// 判断是否超过横向边界
        /// </summary>
        /// <returns></returns>
        private bool IsWidthOutBounds()
        {
            double rate = st.ScaleX;
            if ((rate * img.Width) > bounds.Width)
            {
                return true;
            }
            return false;
        }
    }

 

调用该用户控件:

View Code
loadingImage.OriginalImage = img;
loadingImage.Uri = item.Uri;
 loadingImage.Show();

 

posted @ 2012-11-17 16:24  欧西  阅读(302)  评论(0编辑  收藏  举报