windows8 開發教程 教你製作 多點觸控Helper可將任意容器內任意對象進行多點縮放

實現方法:


 

對Manipulation進行抽象化 使不同容器可共用多點縮放事件,

C# 代碼如下:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;

namespace MetroTimeline
{
    public class MetroManipulationHelper
    {
        /// <summary>
        /// 發生碰撞時的操作方法庫
        /// </summary>
        public static Dictionary<Predicate<string>, Action<ManipulationDeltaRoutedEventArgs>>
            BoundaryFeedbackDict = new Dictionary<Predicate<string>, Action<ManipulationDeltaRoutedEventArgs>>();

        /// <summary>
        /// 多點觸控開始後方法庫
        /// </summary>
        public static Dictionary<Predicate<string>, Action<ManipulationStartedRoutedEventArgs>>
            ManipulationStartedDict = new Dictionary<Predicate<string>, Action<ManipulationStartedRoutedEventArgs>>();

        /// <summary>
        /// 多點觸控完成後方法庫
        /// </summary>
        public static Dictionary<Predicate<string>, Action<ManipulationCompletedRoutedEventArgs>>
            ManipulationCompletedDict = new Dictionary<Predicate<string>, Action<ManipulationCompletedRoutedEventArgs>>();


        /// <summary>
        /// 需要執行的方法的關鍵字
        /// </summary>
        private static string methodTag;

        public static string MethodTag
        {
            get { return MetroManipulationHelper.methodTag; }
            set { MetroManipulationHelper.methodTag = value; }
        }


        /// <summary>
        /// 將容器變爲多點操控容器
        /// </summary>
        /// <param name="container"></param>
        /// <param name="mode"></param>
        /// <param name="trans"></param>
        /// <param name="scale"></param>
        /// <param name="rotation"></param>
        /// <param name="containerRect">容器相對父級菜單位置</param>
        public static void InitManipulation(FrameworkElement container, ManipulationModes mode,
            double trans, double scale, double rotation, Rect containerRect)
        {

            BoundaryFeedbackDict.Add(s => s.Equals("default"), e =>
            {
                var element = e.OriginalSource as FrameworkElement;
                var con = e.Container as Panel;
                var elementBounds = element.RenderTransform.TransformBounds(new Rect(e.Position, element.RenderSize));
                Point fp = new Point((elementBounds.Left + elementBounds.Right) / 2, (elementBounds.Top + elementBounds.Bottom) / 2);
                if (fp.X < containerRect.Left ||
                    fp.X > containerRect.Right ||
                    fp.Y < containerRect.Top ||
                    fp.Y > containerRect.Bottom)
                {
                    e.Complete();
                }
            });
            container.ManipulationStarting += ElementManipulationEventHandler(container, mode);
            container.ManipulationDelta += ElementManipulationDeltaEventHandler();
            container.ManipulationStarted += ElementManipulationStartedEventHandler();
            container.ManipulationCompleted += ElementManipulationCompletedEventHandler();
            container.ManipulationInertiaStarting += ElementManipulationInertiaStartingEventHandler(trans, scale, rotation);
            foreach (var item in (container as Panel).Children)
            {
                if (item.ManipulationMode == ManipulationModes.All)
                {
                    var group = new TransformGroup();
                    group.Children.Add(new TranslateTransform());
                    group.Children.Add(new ScaleTransform());
                    group.Children.Add(new RotateTransform());
                    item.RenderTransform = group;
                }
            }
        }



        #region 多點手勢方法
        #region 多點觸控手勢開始操作
        public static ManipulationStartingEventHandler ElementManipulationEventHandler(FrameworkElement element, ManipulationModes mode)
        {
            return (sender, e) =>
            {
                e.Container = element;
                e.Mode = mode;
            };
        }
        #endregion

        #region 多點觸控手勢過程中操作
        public static ManipulationDeltaEventHandler ElementManipulationDeltaEventHandler()
        {
            return ((sender, e) =>
            {
                var element = e.OriginalSource as FrameworkElement;
                var center = new Point(element.ActualWidth / 2, element.ActualHeight / 2);
                var tt = (element.RenderTransform as TransformGroup).Children[0] as TranslateTransform;
                tt.X += e.Delta.Translation.X;
                tt.Y += e.Delta.Translation.Y;
                var st = (element.RenderTransform as TransformGroup).Children[1] as ScaleTransform;
                st.CenterX = center.X;
                st.CenterY = center.Y;
                st.ScaleX *= e.Delta.Scale;
                st.ScaleY *= e.Delta.Scale;
                var rt = (element.RenderTransform as TransformGroup).Children[2] as RotateTransform;
                rt.CenterX = center.X;
                rt.CenterY = center.Y;
                rt.Angle += e.Delta.Rotation;
                if (e.IsInertial)
                    if (null != BoundaryFeedbackDict)
                        foreach (var item in BoundaryFeedbackDict)
                        {
                            if (null != MethodTag)
                                if (item.Key(MethodTag)) item.Value(e);
                        };
            });
        }
        #endregion

        #region 多點手勢開始後
        private static ManipulationStartedEventHandler ElementManipulationStartedEventHandler()
        {
            return (sender, e) =>
            {
                if (null != ManipulationStartedDict)
                    foreach (var item in ManipulationStartedDict)
                    {
                        if (null != MethodTag)
                            if (item.Key(MethodTag)) item.Value(e);
                    };
            };
        }
        #endregion

        #region 多點手勢完成
        private static ManipulationCompletedEventHandler ElementManipulationCompletedEventHandler()
        {
            return (sender, e) =>
            {
                if (null != ManipulationCompletedDict)
                    foreach (var item in ManipulationCompletedDict)
                    {
                        if (null != MethodTag)
                            if (item.Key(MethodTag)) item.Value(e);
                    };
            };
        }
        #endregion

        #region 多點手勢慣性開始
        /// <summary>
        /// 
        /// </summary>
        /// <param name="trans">10</param>
        /// <param name="scale">0.1</param>
        /// <param name="rotation">540</param>
        /// <returns></returns>
        private static ManipulationInertiaStartingEventHandler ElementManipulationInertiaStartingEventHandler(double trans, double scale, double rotation)
        {
            return (sender, e) =>
            {
                e.TranslationBehavior.DesiredDeceleration = trans * 96.0 / (1000.0 * 1000.0);
                e.ExpansionBehavior.DesiredDeceleration = scale * 96 / 1000.0 * 1000.0;
                e.RotationBehavior.DesiredDeceleration = rotation / (1000.0 * 1000.0);
            };
        }
        #endregion
        #endregion
    }
}

 

xaml :

<Page
    x:Class="MetroTimeline.MainPage"
    IsTabStop="false"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MetroTimeline"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Canvas Background="{StaticResource ApplicationPageBackgroundThemeBrush}"
          Width="1080" Height="500"
          x:Name="cvsContent" Tag="default">
        <TextBlock Canvas.Left="573" TextWrapping="Wrap" Text="TextBlock" x:Name="tbInfo" ManipulationMode="All" Margin="219,597,171,10"/>
        <Image Source="Assets/PicWallLoading.jpg" ManipulationMode="All" Height="202" Canvas.Left="75" Canvas.Top="209" Width="153"/>
        <Image Source="Assets/PicWallLoading.jpg" ManipulationMode="All" Height="202" Canvas.Left="333" Canvas.Top="83" Width="153"/>
    </Canvas>
</Page>


 

使用方式:

 

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace MetroTimeline
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();         
            var conRect = new Rect(Canvas.GetLeft(cvsContent), Canvas.GetTop(cvsContent),
                cvsContent.Width, cvsContent.Height);
            MetroManipulationHelper.InitManipulation(cvsContent, ManipulationModes.All, 5, 0.5, 360, conRect);
            MetroManipulationHelper.MethodTag = cvsContent.Tag.ToString();
        }

        /// <summary>
        /// Invoked when this page is about to be displayed in a Frame.
        /// </summary>
        /// <param name="e">Event data that describes how this page was reached.  The Parameter
        /// property is typically used to configure the page.</param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }
    }
}


 

 

conRect 爲當前需要操作的容器 相對他父級容器的大小以及位置,用於判斷多點元素的活動範圍,

如果範圍是全屏的話 則無需傳該參數,進行相應修改即可

 

最後是效果圖:

 

 

demo 下載地址:http://download.csdn.net/detail/wangrenzhu2011/4420853

發佈了38 篇原創文章 · 獲贊 35 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章