Back to Devexpress

How to: Implement a Custom Funnel Animation

windowsforms-117078-controls-and-libraries-chart-control-examples-end-user-interaction-how-to-implement-a-custom-funnel-animation.md

latest6.4 KB
Original Source

How to: Implement a Custom Funnel Animation

  • Nov 13, 2018
  • 3 minutes to read

To implement a custom bar animation, design a class inheriting the FunnelAnimationBase class and override the FunnelAnimationBase.ApplyState method which determines the transformations applied to an individual funnel point.

csharp
using DevExpress.XtraCharts;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace AnimationExample {
    class FanFunnelAnimation : FunnelAnimationBase {
        const float AnimationStartAngle = 270;
        const float MaxSweepAngle = 180;
        const float HalfMaxSweepAngle = 90;

        public override void ApplyState(
                SceneModifier modifier, 
                RectangleF diagramBounds, 
                FunnelSeriesPointLayoutParameters funnelParameters, 
                float progress
        ) {
            RectangleF funnelBounds = funnelParameters.Bounds;
            float fanCenterX = funnelBounds.Left + funnelBounds.Width / 2;
            float fanCenterY = funnelBounds.Bottom;
            float fanRadius = (float)Math.Sqrt(
                    (funnelBounds.Left - fanCenterX) * (funnelBounds.Left - fanCenterX)
                    + (funnelBounds.Height) * (funnelBounds.Height)
            );

            float startAngle = AnimationStartAngle - HalfMaxSweepAngle * progress;
            float sweepAngle = MaxSweepAngle * progress;
            float endAngle = startAngle + sweepAngle;

            float fanLeftBoundEndX =
                fanCenterX + (float)Math.Cos(startAngle / 180 * Math.PI) * fanRadius;
            float fanLeftBoundEndY =
                fanCenterY + (float)Math.Sin(startAngle / 180 * Math.PI) * fanRadius;

            float fanRightBoundEndX =
                fanCenterX + (float)Math.Cos(endAngle / 180 * Math.PI) * fanRadius;
            float fanRightBoundEndY =
                fanCenterY + (float)Math.Sin(endAngle / 180 * Math.PI) * fanRadius;

            RectangleF fanBounds = new RectangleF(
                    fanCenterX - fanRadius,
                    fanCenterY - fanRadius,
                    2 * fanRadius,
                    2 * fanRadius
            );

            GraphicsPath path = new GraphicsPath();
            path.AddLine(fanCenterX, fanCenterY, fanLeftBoundEndX, fanLeftBoundEndY);
            path.AddArc(fanBounds, startAngle, sweepAngle);
            path.AddLine(fanRightBoundEndX, fanRightBoundEndY, fanCenterX, fanCenterY);
            modifier.Clip(path);

        }

        protected override ChartElement CreateObjectForClone() {
            return new FanFunnelAnimation();
        }
    }
}
csharp
protected override void OnLoad(EventArgs e) {
    base.OnLoad(e);

    view.Animation = new FanFunnelAnimation {
        BeginTime = new TimeSpan(0, 0, 0),
        Duration = new TimeSpan(0, 0, 0, 1, 500),
        PointDelay = new TimeSpan(0, 0, 0, 0, 500),
        PointOrder = PointAnimationOrder.Straight,
        EasingFunction = new LinearEasingFunction {
            EasingMode = EasingMode.Out
        }
    };

    chartControl.AnimationStartMode = ChartAnimationMode.OnLoad;
}

private void OnAnimateClick(object sender, EventArgs e) {
    chartControl.Animate();
}
vb
Imports DevExpress.XtraCharts
Imports System
Imports System.Drawing
Imports System.Drawing.Drawing2D

Namespace AnimationExample
    Friend Class FanFunnelAnimation
        Inherits FunnelAnimationBase

        Private Const AnimationStartAngle As Single = 270
        Private Const MaxSweepAngle As Single = 180
        Private Const HalfMaxSweepAngle As Single = 90

        Public Overrides Sub ApplyState(ByVal modifier As SceneModifier, ByVal diagramBounds As RectangleF, ByVal funnelParameters As FunnelSeriesPointLayoutParameters, ByVal progress As Single)
            Dim funnelBounds As RectangleF = funnelParameters.Bounds
            Dim fanCenterX As Single = funnelBounds.Left + funnelBounds.Width / 2
            Dim fanCenterY As Single = funnelBounds.Bottom
            Dim fanRadius As Single = CSng(Math.Sqrt((funnelBounds.Left - fanCenterX) * (funnelBounds.Left - fanCenterX) + (funnelBounds.Height) * (funnelBounds.Height)))

            Dim startAngle As Single = AnimationStartAngle - HalfMaxSweepAngle * progress
            Dim sweepAngle As Single = MaxSweepAngle * progress
            Dim endAngle As Single = startAngle + sweepAngle

            Dim fanLeftBoundEndX As Single = fanCenterX + CSng(Math.Cos(startAngle / 180 * Math.PI)) * fanRadius
            Dim fanLeftBoundEndY As Single = fanCenterY + CSng(Math.Sin(startAngle / 180 * Math.PI)) * fanRadius

            Dim fanRightBoundEndX As Single = fanCenterX + CSng(Math.Cos(endAngle / 180 * Math.PI)) * fanRadius
            Dim fanRightBoundEndY As Single = fanCenterY + CSng(Math.Sin(endAngle / 180 * Math.PI)) * fanRadius

            Dim fanBounds As New RectangleF(fanCenterX - fanRadius, fanCenterY - fanRadius, 2 * fanRadius, 2 * fanRadius)

            Dim path As New GraphicsPath()
            path.AddLine(fanCenterX, fanCenterY, fanLeftBoundEndX, fanLeftBoundEndY)
            path.AddArc(fanBounds, startAngle, sweepAngle)
            path.AddLine(fanRightBoundEndX, fanRightBoundEndY, fanCenterX, fanCenterY)
            modifier.Clip(path)

        End Sub

        Protected Overrides Function CreateObjectForClone() As ChartElement
            Return New FanFunnelAnimation()
        End Function
    End Class
End Namespace
vb
Protected Overrides Sub OnLoad(ByVal e As EventArgs)
    MyBase.OnLoad(e)

    view.Animation = New FanFunnelAnimation With { _
        .BeginTime = New TimeSpan(0, 0, 0), .Duration = New TimeSpan(0, 0, 0, 1, 500), .PointDelay = New TimeSpan(0, 0, 0, 0, 500), .PointOrder = PointAnimationOrder.Straight, .EasingFunction = New LinearEasingFunction With {.EasingMode = EasingMode.Out} _
    }

    chartControl.AnimationStartMode = ChartAnimationMode.OnLoad
End Sub

Private Sub OnAnimateClick(ByVal sender As Object, ByVal e As EventArgs) Handles btnAnumate.Click
    chartControl.Animate()
End Sub