windowsforms-116438-controls-and-libraries-chart-control-examples-end-user-interaction-how-to-implement-a-custom-marker-animation.md
To implement a custom bar animation, design a class inheriting the XYMarkerAnimationBase class and override the XYMarkerAnimationBase.ApplyState method which determines the transformations applied to an individual marker.
using DevExpress.XtraCharts;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace AnimationExample {
class FanMarkerAnimation : XYMarkerAnimationBase {
public override void ApplyState(
SceneModifier modifier,
RectangleF diagramBounds,
MarkerSeriesPointLayoutParameters markerParameters,
float progress
) {
RectangleF markerBounds = markerParameters.Bounds;
float markerCenterX = markerBounds.Left + markerBounds.Width / 2;
float markerCenterY = markerBounds.Top + markerBounds.Height / 2;
float startAngle = 360 - progress * 180;
float sweepAngle = 360 * progress;
float endAngle = startAngle + sweepAngle;
// To apply a fan animation we need to compute parameters of
// a marker's circumscribed circle sector.
float circumscribedCircleRadius = (float)Math.Sqrt(
(markerBounds.Left - markerCenterX) * (markerBounds.Left - markerCenterX)
+ (markerBounds.Top - markerCenterY) * (markerBounds.Top - markerCenterY)
);
float circumscribedCircleSectorLeftBoundEndX =
markerCenterX + (float)Math.Cos(startAngle / 180 * Math.PI) * circumscribedCircleRadius;
float circumscribedCircleSectorLeftBoundEndY =
markerCenterY + (float)Math.Sin(startAngle / 180 * Math.PI) * circumscribedCircleRadius;
float circumscribedCircleSectorRightBoundEndX =
markerCenterX + (float)Math.Cos(endAngle / 180 * Math.PI) * circumscribedCircleRadius;
float circumscribedCircleSectorRightBoundEndY =
markerCenterY + (float)Math.Sin(endAngle / 180 * Math.PI) * circumscribedCircleRadius;
RectangleF circumscribedCircleBounds = new RectangleF(
markerCenterX - circumscribedCircleRadius,
markerCenterY - circumscribedCircleRadius,
2 * circumscribedCircleRadius,
2 *circumscribedCircleRadius
);
// Path representing a marker's circumscribed circle sector.
GraphicsPath path = new GraphicsPath();
path.AddLine(
markerCenterX,
markerCenterY,
circumscribedCircleSectorLeftBoundEndX,
circumscribedCircleSectorLeftBoundEndY
);
path.AddArc(
circumscribedCircleBounds,
startAngle,
sweepAngle
);
path.AddLine(
circumscribedCircleSectorRightBoundEndX,
circumscribedCircleSectorRightBoundEndY,
markerCenterX,
markerCenterY
);
modifier.Clip(path);
}
protected override ChartElement CreateObjectForClone() {
return new FanMarkerAnimation();
}
}
}
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
chartControl.AnimationStartMode = ChartAnimationMode.OnLoad;
view.SeriesPointAnimation = new FanMarkerAnimation() {
BeginTime = new TimeSpan(0, 0, 0),
Duration = new TimeSpan(0, 0, 0, 1, 500),
PointDelay = new TimeSpan(0, 0, 0, 0, 250),
PointOrder = PointAnimationOrder.Random,
EasingFunction = new QuinticEasingFunction {
EasingMode = EasingMode.Out
}
};
}
private void OnAnimateClick(object sender, EventArgs e) {
chartControl.Animate();
}
Protected Overrides Sub OnLoad(ByVal e As EventArgs)
MyBase.OnLoad(e)
chartControl.AnimationStartMode = ChartAnimationMode.OnLoad
view.SeriesPointAnimation = New FanMarkerAnimation() With { _
.BeginTime = New TimeSpan(0, 0, 0), .Duration = New TimeSpan(0, 0, 0, 1, 500), .PointDelay = New TimeSpan(0, 0, 0, 0, 250), .PointOrder = PointAnimationOrder.Random, .EasingFunction = New QuinticEasingFunction With {.EasingMode = EasingMode.Out} _
}
End Sub
Private Sub OnAnimateClick(ByVal sender As Object, ByVal e As EventArgs) Handles button1.Click, btnAnimate.Click
chartControl.Animate()
End Sub
Imports DevExpress.XtraCharts
Imports System
Imports System.Drawing
Imports System.Drawing.Drawing2D
Namespace AnimationExample
Friend Class FanMarkerAnimation
Inherits XYMarkerAnimationBase
Public Overrides Sub ApplyState(ByVal modifier As SceneModifier, ByVal diagramBounds As RectangleF, ByVal markerParameters As MarkerSeriesPointLayoutParameters, ByVal progress As Single)
Dim markerBounds As RectangleF = markerParameters.Bounds
Dim markerCenterX As Single = markerBounds.Left + markerBounds.Width / 2
Dim markerCenterY As Single = markerBounds.Top + markerBounds.Height / 2
Dim startAngle As Single = 360 - progress * 180
Dim sweepAngle As Single = 360 * progress
Dim endAngle As Single = startAngle + sweepAngle
' To apply a fan animation we need to compute parameters of
' a marker's circumscribed circle sector.
Dim circumscribedCircleRadius As Single = CSng(Math.Sqrt((markerBounds.Left - markerCenterX) * (markerBounds.Left - markerCenterX) + (markerBounds.Top - markerCenterY) * (markerBounds.Top - markerCenterY)))
Dim circumscribedCircleSectorLeftBoundEndX As Single = markerCenterX + CSng(Math.Cos(startAngle / 180 * Math.PI)) * circumscribedCircleRadius
Dim circumscribedCircleSectorLeftBoundEndY As Single = markerCenterY + CSng(Math.Sin(startAngle / 180 * Math.PI)) * circumscribedCircleRadius
Dim circumscribedCircleSectorRightBoundEndX As Single = markerCenterX + CSng(Math.Cos(endAngle / 180 * Math.PI)) * circumscribedCircleRadius
Dim circumscribedCircleSectorRightBoundEndY As Single = markerCenterY + CSng(Math.Sin(endAngle / 180 * Math.PI)) * circumscribedCircleRadius
Dim circumscribedCircleBounds As New RectangleF(markerCenterX - circumscribedCircleRadius, markerCenterY - circumscribedCircleRadius, 2 * circumscribedCircleRadius, 2 *circumscribedCircleRadius)
' Path representing a marker's circumscribed circle sector.
Dim path As New GraphicsPath()
path.AddLine(markerCenterX, markerCenterY, circumscribedCircleSectorLeftBoundEndX, circumscribedCircleSectorLeftBoundEndY)
path.AddArc(circumscribedCircleBounds, startAngle, sweepAngle)
path.AddLine(circumscribedCircleSectorRightBoundEndX, circumscribedCircleSectorRightBoundEndY, markerCenterX, markerCenterY)
modifier.Clip(path)
End Sub
Protected Overrides Function CreateObjectForClone() As ChartElement
Return New FanMarkerAnimation()
End Function
End Class
End Namespace