【问题标题】:Viewport Origin animation视口原点动画
【发布时间】:2014-04-12 14:09:43
【问题描述】:

我正在开发一个 Windows 手机应用程序,其中有一个 viewportcontroller,它使我能够放大和缩小内容。 我想将缩放中心放在我缩放的点上。我能做的事

Viewportcontroller.SetViewportOrigin()

但这会使视口控制器跳转到我设置的原点。这看起来不太好。因此,我想创建一个故事板,随着缩放的发生逐渐改变原点。

因此我想问我应该如何使用 ViewportControl 的属性来做到这一点。我尝试了一些不同的动画类型,翻译和 xy。但是要么我选择了错误的属性,要么选择了错误的动画类型。因为没有任何工作:(

因此,我的问题是双重的。 我选择什么类型的动画。我该如何改变它? 它应该是一个 DoubleAnimation 我在哪里设置和从哪里开始?但我似乎无法在这里设定一个点?非常感谢任何帮助!

【问题讨论】:

    标签: c# animation windows-phone-8 storyboard


    【解决方案1】:

    我没有使用 ViewportControl 的经验,我假设 ViewportControl.SetViewportOrigin() 是设置原点的唯一方法(即:没有属性可以这样做)。

    如果是这种情况,您可以将 ViewportControl 包装在自定义控件中。

    添加两个控制的依赖属性(ViewportX 和 ViewportY,或一个 Point 类型的依赖属性),并在情节提要中为这两个属性设置动画(使用简单的 DoubleAnimation)。

    在这些属性的值更改回调中,您可以使用更改后的值调用 SetViewportOrigin()。

    类似:

    public class WrappedViewport : Control
    {
        private ViewportControl _viewportControl;
        protected override OnApplyTemplate()
        {
            // make sure there is an appropriate default style in generic.xaml
            _viewportControl = (ViewportControl)GetTemplateChild("Viewport"); 
        }
    
        #region ViewportX
        private static void ViewportXChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WrappedViewport owner = (WrappedViewport)d;
            owner._viewportControl.SetViewportOrigin(ViewportX, ViewportY);
        }
    
        private static readonly DependencyProperty ViewportXProperty = DependencyProperty.Register("ViewportX",
                                                                                              typeof(double),
                                                                                              typeof(WrappedViewport),
                                                                                              new PropertyMetadata(0d, ViewportXChangedCallback));
    
        public double ViewportX
        {
            get { return (double)GetValue(ViewportXProperty ); }
            set { SetValue(ViewportXProperty , value); }
        }
        #endregion
    
        #region ViewportY
        private static void ViewportYChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WrappedViewport owner = (WrappedViewport)d;
            owner._viewportControl.SetViewportOrigin(ViewportX, ViewportY);
        }
    
        private static readonly DependencyProperty ViewportYProperty = DependencyProperty.Register("ViewportY",
                                                                                              typeof(double),
                                                                                              typeof(WrappedViewport),
                                                                                              new PropertyMetadata(0d, ViewportYChangedCallback));
    
        public double ViewportY
        {
            get { return (double)GetValue(ViewportYProperty ); }
            set { SetValue(ViewportYProperty , value); }
        }
        #endregion
    }
    

    另见http://msdn.microsoft.com/en-us/library/ms752914(v=vs.110).aspx

    【讨论】:

    • @Willvanrumpt 我还没有找到另一种设置中心的方法。好的,我从来没有玩过 Dependency 属性,你能解释一下代码中发生了什么以及应该在 (...) 处放什么吗?
    • 谢谢,稍后我会试试的。
    • 在 OnApplyTemplate 中,您忘记了一个空白。在 setViewportOrigin 中需要一个点。 ViewportX 和 ViewportY,给出错误。要解决此错误,我需要将变量更改为静态。使用 get 和 set 时哪个引入了错误?你能帮我解决这个错误吗?
    【解决方案2】:

    我尝试了几种不同的方法,结果证明这是最流畅的。它不漂亮,但它有效。

    public partial class MainPage : PhoneApplicationPage
    {
        private const int MoveCount = 25;
    
        private double _tickX;
        private double _tickY;
    
        private int _adjustCount = MoveCount+1;
    
        public MainPage()
        {
            InitializeComponent();
            Viewport.ViewportChanged += ViewportOnViewportChanged;
        }
    
        private void ViewportOnViewportChanged(object sender, ViewportChangedEventArgs viewportChangedEventArgs)
        {
            AdjstViewport();
        }
    
        private void AdjstViewport()
        {
            if (_adjustCount >= MoveCount) return;
            _adjustCount++;
            Viewport.SetViewportOrigin(new Point(Viewport.Viewport.X + _tickX, Viewport.Viewport.Y + _tickY));                        
        }
    
        private async void OnButtonClick(object sender, System.Windows.RoutedEventArgs e)
        {
            _adjustCount = 0;
    
            var content = (FrameworkElement)Viewport.Content;
            double zoomOriginX = (content.ActualWidth / 2) - (Viewport.Viewport.Width / 2);
            double zoomOriginY = (content.ActualHeight / 2) - (Viewport.Viewport.Height / 2);
    
            double distanceX = zoomOriginX - Viewport.Viewport.X;
            double distanceY = zoomOriginY - Viewport.Viewport.Y;
    
            _tickX = distanceX / MoveCount;
            _tickY = distanceY / MoveCount;
    
            AdjstViewport();
        }
    }
    

    【讨论】:

    • 感谢您查看我的另一个问题 :) 好的,所以我当然想使用捏缩放来做到这一点。所以你通过事件而不是动画来做到这一点。我可以看到这可能会奏效。我稍后会尝试一下。但我们正忙于处理其他一些问题,以尝试在丹麦时间周日晚上提交 ImagineCup。所以我们有一个更紧迫的问题来使用 ViewPort。如果您有时间,我们希望在stackoverflow.com/questions/22717113/… 上提供一些帮助,只是用尽所有可能性:)
    • 我先尝试了动画,但这是最流畅的
    猜你喜欢
    • 2015-06-09
    • 2018-08-07
    • 1970-01-01
    • 2012-12-18
    • 2019-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多