微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

WPF/Silverligh实现图片的放大缩小拖动

实现功能如下

  1. 以滚轮中心点对图片容器进行放大和缩小
  2. 对放大后的图片进行拖动
  3. 对拖动的范围进行控制

         由于在后续的功能中需要动态加载不同的图片,所以此示例中是针对grid的放大和缩小,图片自动填充的!

本人头脑比较笨,用最简单的原理来实现的,实现原理如下:

1.放大操作

假设我们要对(1.5,1.5)这个点为中心进行放大,那么放大1倍后,应该是矩形2的位置,需要将(3,3)的点移动到原来点的位置,需要将矩形2向上移动1.5,向左移动1.5

ScaleTransform放大1倍,TranslateTransform移动为(-1.5,-1.5).得出如下图所示

2.移动后放大,放大后移动再放大等情况

看下图的情况:我们将矩形1向左移动1个单位后,再放大1倍

当我们点击相对于原点(2.5,1.5)的点时,实际上我们想放大的是相对于矩形1(1.5,1.5)的点!那么我们首先利用矩阵的逆变换得到相对于矩形1的点。然后对矩形1的点(1.5,1.5)进行放大1倍的处理,重复步骤1(放大操作)。

然后再计算出(2.5,1.5)与逆变换后(1.5,1.5)的偏移距离,将TranslateTransform再次移动(1,0)。即得到所要的矩形2,如下图

下面是实现的代码

界面层,我使用GrdMap来作为变换的对象,GrdMap的内容为1.jpg图片(也可以是其他控件等各类元素)。这里使用GrdRelative作为参照物(起到原点的作用,原始图片位置)。注意里面的元素数据绑定,可以做到自适应屏幕,所有宽度和高度不指定。slider可用可不用,自己修改

<Window x:Class="WpfMap.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Height="350"
        Width="525">
    <Grid x:Name="Grd">
        <Grid x:Name="GrdRelative"
              HorizontalAlignment="Center"
              VerticalAlignment="Center"
              Width="{Binding ActualWidth,ElementName=GrdMap}"
              Height="{Binding ActualHeight,ElementName=GrdMap}"></Grid>
        <Grid x:Name="GrdMap"
              MouseWheel="GrdMap_MouseWheel"
              MouseLeave="GrdMap_MouseLeave"
              MouseDown="GrdMap_MouseDown"
              MouseUp="GrdMap_MouseUp"
              MouseMove="GrdMap_MouseMove"
              HorizontalAlignment="Center"
              VerticalAlignment="Center"
              RenderTransformOrigin="0,0">
            <Grid.RenderTransform>
                <TransformGroup>
                    <ScaleTransform ScaleX="{Binding Value,ElementName=slider}"
                                    ScaleY="{Binding Value,ElementName=slider}" />
                    <SkewTransform />
                    <RotateTransform />
                    <TranslateTransform />
                </TransformGroup>
            </Grid.RenderTransform>
            <Image Source="1.jpg" />
        </Grid>
        <Slider x:Name="slider"
                HorizontalAlignment="Left"
                VerticalAlignment="Center"
                Orientation="Vertical"
                Width="20"
                Height="200"
                Maximum="3"
                Minimum="1" />
    </Grid>
</Window>


后台代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfMap
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
        }

        ScaleTransform st;
        TranslateTransform tt;
        TransformGroup group;
        bool isDrag = false;
        Point startPoint;

        void MainWindow_Loaded(object sender,RoutedEventArgs e)
        {
            group = (TransformGroup)GrdMap.RenderTransform;
            st = group.Children[0] as ScaleTransform;
            tt = group.Children[3] as TranslateTransform;
        }

        private void GrdMap_MouseWheel(object sender,MouseWheelEventArgs e)
        {
            var point = e.GetPosition(GrdRelative); // 实际点击的点
            var actualPoint = group.Inverse.Transform(point); // 想要缩放的点
            slider.Value = slider.Value + (double)e.Delta / 1000;
            tt.X = -((actualPoint.X * (slider.Value - 1))) + point.X - actualPoint.X;
            tt.Y = -((actualPoint.Y * (slider.Value - 1))) + point.Y - actualPoint.Y;
        }

        private void GrdMap_MouseDown(object sender,MouseButtonEventArgs e)
        {
            isDrag = true;
            startPoint = e.GetPosition(GrdRelative);
        }

        private void GrdMap_MouseUp(object sender,MouseButtonEventArgs e)
        {
            isDrag = false;
        }

        private void GrdMap_MouseLeave(object sender,MouseEventArgs e)
        {
            isDrag = false;
        }

        private void GrdMap_MouseMove(object sender,MouseEventArgs e)
        {
            if (isDrag)
            {
                Point p = e.GetPosition(GrdRelative);
                Point topPoint = GrdMap.TranslatePoint(new Point(0,0),GrdRelative);
                Point bottomPoint = GrdMap.TranslatePoint(new Point(GrdMap.ActualWidth,GrdMap.ActualHeight),GrdRelative);

                double moveX = p.X - startPoint.X;
                double moveY = p.Y - startPoint.Y;

                //向上向下移动条件判断(会有一点点的小偏移,如果想更精确的控制,那么分向上和向下两种情况,并判断边距)
                if ((moveY < 0 && bottomPoint.Y > GrdRelative.ActualHeight) || (moveY > 0 && topPoint.Y < 0))
                {
                    tt.Y += (p.Y - startPoint.Y);
                    startPoint.Y = p.Y;
                }

                //向左向右移动条件判断
                if ((moveX < 0 && bottomPoint.X > GrdRelative.ActualWidth) || (moveX > 0 && topPoint.X < 0))
                {
                    tt.X += (p.X - startPoint.X);
                    startPoint.X = p.X;
                }
            }
        }
    }
}


代码很简单,也没有写过多的注释!

下载代码需要2个积分,其实以上的代码段已经包含所有代码了!

以下是源码地址,vs2010,可直接运行!

http://download.csdn.net/detail/wuwo333/5308725

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐