public void Start(Action <StrokeDash> onValueCallback) { _currStrokeDash = From; var anim = new Animation(_ => onValueCallback(_currStrokeDash)); anim.Add(0, 1, new Animation( callback: v => _currStrokeDash.Phase = (float)v, start: From.Phase, end: To.Phase, easing: Easing)); anim.Add(0, 1, new Animation( callback: v => _currStrokeDash.Intervals[0] = (float)v, start: From.Intervals[0], end: To.Intervals[0], easing: Easing)); anim.Add(0, 1, new Animation( callback: v => _currStrokeDash.Intervals[1] = (float)v, start: From.Intervals[1], end: To.Intervals[1], easing: Easing)); anim.Commit( owner: Application.Current.MainPage, name: "highlightAnimation", length: (uint)Duration.TotalMilliseconds); }
void DrawDash(SKCanvasView skCanvasView, StrokeDash fromDash, StrokeDash toDash) { if (fromDash != null) { var anim = new StrokeDashAnimation( from: fromDash, to: toDash, duration: _highlightSettings.AnimationDuration); anim.Start((strokeDashToDraw) => RequestDraw(skCanvasView, strokeDashToDraw)); } else { RequestDraw(skCanvasView, toDash); } }
public void Draw(SKCanvasView skCanvasView, SKCanvas skCanvas) { skCanvas.Clear(); if (_highlightState == null) { return; } if (_skPaint == null) { _skPaint = CreateHighlightSkPaint(skCanvasView, _highlightSettings, _highlightState.HighlightPath); } StrokeDash strokeDash = _highlightState.StrokeDash; // Comment the next line to see whole path without dash effect _skPaint.PathEffect = SKPathEffect.CreateDash(strokeDash.Intervals, strokeDash.Phase); skCanvas.DrawPath(_highlightState.HighlightPath.Path, _skPaint); }
public void HighlightElement(View viewToHighlight, SKCanvasView skCanvasView, Layout <View> formLayout) { IList <View> layoutChildren = formLayout.Children; if (_highlightState == null) { var path = HighlightPath.Create(skCanvasView, layoutChildren, _highlightSettings.StrokeWidth); _highlightState = new HighlightState() { HighlightPath = path }; } HighlightPath highlightPath = _highlightState.HighlightPath; int currHighlightViewId = _highlightState.CurrHighlightedViewId; int iViewIdToHighlight = highlightPath.GetViewId(layoutChildren, viewToHighlight); if (currHighlightViewId == iViewIdToHighlight) { return; } StrokeDash fromDash; if (currHighlightViewId != -1) { fromDash = _highlightState.StrokeDash; } else { fromDash = new StrokeDash(highlightPath.GetDashForView(layoutChildren, iViewIdToHighlight)); } _highlightState.CurrHighlightedViewId = iViewIdToHighlight; StrokeDash toDash = new StrokeDash(highlightPath.GetDashForView(layoutChildren, viewToHighlight)); DrawDash(skCanvasView, fromDash, toDash); }
public static HighlightPath Create(SKCanvasView skCanvasView, IList <View> layoutChildren, double strokeWidth) { var path = new SKPath(); var highlightPath = new HighlightPath() { Path = path }; strokeWidth = (float)skCanvasView.FromPixels(new Point(0, strokeWidth)).Y; foreach (View view in layoutChildren) { int iStrokeDashCount = highlightPath.DashCount; Rectangle viewBounds = skCanvasView.FromPixels(view.Bounds); if (!(view is Entry) && !(view is Button)) { continue; } if (path.Points.Length == 0) { // Move path point at the left and below of the view path.MoveTo( x: (float)viewBounds.X, y: (float)viewBounds.Y + (float)viewBounds.Height + (float)strokeWidth / 2); } float xCurr = path.LastPoint.X; float yCurr = path.LastPoint.Y; // Add arch for views except first one if (iStrokeDashCount > 0) { float d = iStrokeDashCount % 2 == 0 ? -1 : 1; float arcHeight = (float)viewBounds.Y + (float)viewBounds.Height - path.LastPoint.Y + (float)strokeWidth / 2; path.ArcTo(new SKRect(xCurr - arcHeight / 2, yCurr, xCurr + arcHeight / 2, yCurr + arcHeight), -90, 180 * d, false); } float dashOffset = new SKPathMeasure(path).Length; // Add line below the view // If it's not the first view, the start point is the end from arc end point // and line direction is either to view start or view end path.LineTo((float)viewBounds.X + (float)viewBounds.Width * (iStrokeDashCount % 2 == 0 ? 1 : 0), path.LastPoint.Y); if (view is Button) { xCurr = path.LastPoint.X; yCurr = path.LastPoint.Y; // Draw arc from below button to above button float d = iStrokeDashCount % 2 == 0 ? -1 : 1; float arcHeight = (float)viewBounds.Height + (float)strokeWidth; path.ArcTo(new SKRect(xCurr - arcHeight / 2, yCurr - arcHeight, xCurr + arcHeight / 2, yCurr), 90, 180 * d, false); // Draw horizontal line above the button path.LineTo(xCurr + (float)viewBounds.Width * d, path.LastPoint.Y); // Draw arc pointing down xCurr = path.LastPoint.X; yCurr = path.LastPoint.Y; path.ArcTo(new SKRect(xCurr - arcHeight / 2, yCurr, xCurr + arcHeight / 2, yCurr + arcHeight), -90, 180 * d, false); } float solidDashLength = new SKPathMeasure(path).Length - dashOffset; var strokeDash = new StrokeDash( intervals: new float[] { solidDashLength, 0 }, phase: -dashOffset); highlightPath.SetDashForView(layoutChildren, view, strokeDash); } // Compute the 2nd value of interval, which is the length of remaining path float pathLength = new SKPathMeasure(path).Length; for (int i = 0; i < highlightPath.DashCount; ++i) { StrokeDash d = highlightPath.GetDash(i); d.Intervals[1] = pathLength - d.Intervals[0]; } return(highlightPath); }
public void SetDashForView(IList <View> layoutChildren, View view, StrokeDash strokeDash) => _strokeDashList[GetViewId(layoutChildren, view)] = strokeDash;
void RequestDraw(SKCanvasView skCanvasView, StrokeDash strokeDashToDraw) { _highlightState.StrokeDash = strokeDashToDraw; skCanvasView.InvalidateSurface(); }
public StrokeDash(StrokeDash strokeDash) : this(strokeDash.Intervals, strokeDash.Phase) { }
public StrokeDashAnimation(StrokeDash from, StrokeDash to, TimeSpan duration) { From = from; To = to; Duration = duration; }