How to create smooth animation in code at runtime?

On my page, I create bombs that should be removed for the specified purposes. My problem is what is being used (Timer, DoubleAnimation, KeyFrameAnimation), the movement of the falling bombs seems jerky. Can anyone suggest how to create jerk-free animations (in code). Thank..

+3
source share
3 answers

First of all, testing animations is a bit problematic. I made some animations that work terribly in eumulator (although I meet all the requirements like WDDM 1.1), but they work fine on the device. You just need to check it on the device.

​​, DispatcherTimer ( HelloWorld, ). , .

, DobuleAnimation. ( Timer Tick):

        Random random = new Random();
        // Create the bomb.
        Bomb bomb = new Bomb();
        bomb.IsFalling = true;

        //Easing function
        var easefall = new QuadraticEase();
        easefall.EasingMode = EasingMode.EaseIn;

        // make some bombs bigger and goes faster
        var randNumber = random.Next(0, 100);
        if (randNumber < 15)
        {
            bomb.Scale.ScaleX = bomb.Scale.ScaleY = 0.8;
            Canvas.SetZIndex(bomb, 1);
        }

        // Position the bomb.            
        bomb.SetValue(Canvas.LeftProperty, (double)(random.Next(0, (int)(canvasBackground.ActualWidth - 30))));
        bomb.SetValue(Canvas.TopProperty, -200.0);

        // Attach ManipulationStarted click event (for defusing the bomb).
        bomb.ManipulationStarted += bomb_ManipulationStarted;

        // Create the animation for the falling bomb.
        Storyboard storyboard = new Storyboard();
        DoubleAnimation fallAnimation = new DoubleAnimation();
        fallAnimation.To = canvasBackground.ActualHeight;
        fallAnimation.Duration = TimeSpan.FromSeconds(m_secondsToFall);
        fallAnimation.EasingFunction = easefall;

        StoryBoardHelper.SetTarget(fallAnimation, bomb);
        Storyboard.SetTargetProperty(fallAnimation, new PropertyPath("(Canvas.Top)"));
        storyboard.Children.Add(fallAnimation);

        // Create the animation for the bomb "wiggle."
        DoubleAnimation wiggleAnimation = new DoubleAnimation();
        wiggleAnimation.To = 40;
        wiggleAnimation.Duration = TimeSpan.FromSeconds(0.3);
        wiggleAnimation.RepeatBehavior = RepeatBehavior.Forever;
        wiggleAnimation.AutoReverse = true;
        var easewiggle = new CircleEase();

        easewiggle.EasingMode = EasingMode.EaseInOut;
        wiggleAnimation.EasingFunction = easewiggle;

        StoryBoardHelper.SetTarget(wiggleAnimation, ((TransformGroup)bomb.RenderTransform).Children[0]);
        Storyboard.SetTargetProperty(wiggleAnimation, new PropertyPath("Angle"));
        storyboard.Children.Add(wiggleAnimation);

        // Add the bomb to the Canvas.
        canvasBackground.Children.Add(bomb);

        // Add the storyboard to the tracking collection.            
        m_storyboards.Add(bomb, storyboard);

        // Configure and start the storyboard.
        storyboard.Duration = fallAnimation.Duration;
        storyboard.Completed += storyboard_Completed;
        storyboard.Begin();

, /. :

    // display falling bombs
    private void bomb_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
    {
        FrameworkDispatcher.Update();
        // Get the bomb.
        Bomb bomb = (Bomb)sender;
        bomb.IsFalling = false;

        // Get the bomb current position.
        Storyboard storyboard = m_storyboards[bomb];
        double currentTop = Canvas.GetTop(bomb);

        // Stop the bomb from falling.
        storyboard.Stop();

        // Play the sound
        m_beep.Play();

        // Reuse the existing storyboard, but with new animations.
        // Send the bomb on a new trajectory by animating Canvas.Top
        // and Canvas.Left.
        storyboard.Children.Clear();

        DoubleAnimation riseAnimation = new DoubleAnimation();
        riseAnimation.From = currentTop;
        riseAnimation.To = 0;
        riseAnimation.Duration = TimeSpan.FromSeconds(2);

        StoryBoardHelper.SetTarget(riseAnimation, bomb);
        Storyboard.SetTargetProperty(riseAnimation, new PropertyPath("(Canvas.Top)"));
        storyboard.Children.Add(riseAnimation);

        DoubleAnimation slideAnimation = new DoubleAnimation();
        double currentLeft = Canvas.GetLeft(bomb);
        // Throw the bomb off the closest side.
        if (currentLeft < canvasBackground.ActualWidth / 2)
        {
            slideAnimation.To = -100;
        }
        else
        {
            slideAnimation.To = canvasBackground.ActualWidth + 100;
        }
        slideAnimation.Duration = TimeSpan.FromSeconds(1);
        StoryBoardHelper.SetTarget(slideAnimation, bomb);
        Storyboard.SetTargetProperty(slideAnimation, new PropertyPath("(Canvas.Left)"));
        storyboard.Children.Add(slideAnimation);

        // Start the new animation.
        storyboard.Duration = slideAnimation.Duration;
        storyboard.Begin();
    }

PS: Silverlight:)

+4

, , , , , . :

+1

- Windows , , .

CompositionTarget.Rendering , , ( ) , .

Finally, you can also use the Storyboard / Animation classes to perform animations. I did this in quite a few demo cases now and saw nice, smooth effects - especially when using a real phone, and not when using an emulator (I'm not 100% sure that my own emulation counter starts!)

As Derek says, maybe it's worth seeing what you are animating - replace your current animated objects with simple shapes (like rectangles) and see if they come to life smoothly.

+1
source

Source: https://habr.com/ru/post/1789762/


All Articles