public static Task <bool> BezierPathTo(this VisualElement view, Point pt1, Point pt2, Point pt3, uint length = 250, BezierTangent bezierTangent = BezierTangent.None, Easing easing = null) { easing = easing ?? Easing.Linear; TaskCompletionSource <bool> taskCompletionSource = new TaskCompletionSource <bool>(); WeakReference <VisualElement> weakViewRef = new WeakReference <VisualElement>(view); Rectangle bounds = view.Bounds; BezierSpline bezierSpline = new BezierSpline(bounds.Center, pt1, pt2, pt3); Action <double> callback = t => { VisualElement viewRef; if (weakViewRef.TryGetTarget(out viewRef)) { Point tangent; Point point = bezierSpline.GetPointAtFractionLength(t, out tangent); double x = point.X - bounds.Width / 2; double y = point.Y - bounds.Height / 2; viewRef.Layout(new Rectangle(new Point(x, y), bounds.Size)); if (bezierTangent != BezierTangent.None) { viewRef.Rotation = 180 * Math.Atan2(tangent.Y, tangent.X) / Math.PI; if (bezierTangent == BezierTangent.Reversed) { viewRef.Rotation += 180; } } } }; Animation animation = new Animation(callback, 0, 1, easing); animation.Commit(view, "BezierPathTo", 16, length, finished: (value, cancelled) => taskCompletionSource.SetResult(cancelled)); return(taskCompletionSource.Task); }
public static Task<bool> BezierPathTo(this VisualElement view, Point pt1, Point pt2, Point pt3, uint length = 250, BezierTangent bezierTangent = BezierTangent.None, Easing easing = null) { easing = easing ?? Easing.Linear; TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>(); WeakReference<VisualElement> weakViewRef = new WeakReference<VisualElement>(view); Rectangle bounds = view.Bounds; BezierSpline bezierSpline = new BezierSpline(bounds.Center, pt1, pt2, pt3); Action<double> callback = t => { VisualElement viewRef; if (weakViewRef.TryGetTarget(out viewRef)) { Point tangent; Point point = bezierSpline.GetPointAtFractionLength(t, out tangent); double x = point.X - bounds.Width / 2; double y = point.Y - bounds.Height / 2; viewRef.Layout(new Rectangle(new Point(x, y), bounds.Size)); if (bezierTangent != BezierTangent.None) { viewRef.Rotation = 180 * Math.Atan2(tangent.Y, tangent.X) / Math.PI; if (bezierTangent == BezierTangent.Reversed) { viewRef.Rotation += 180; } } } }; Animation animation = new Animation(callback, 0, 1, easing); animation.Commit(view, "BezierPathTo", 16, length, finished: (value, cancelled) => taskCompletionSource.SetResult(cancelled)); return taskCompletionSource.Task; }