/// <summary> /// Draws the value bars. /// </summary> /// <param name="canvas">The canvas.</param> /// <param name="points">The points.</param> /// <param name="itemSize">The item size.</param> /// <param name="origin">The origin.</param> /// <param name="headerHeight">The Header height.</param> protected void DrawBars(SKCanvas canvas, SKPoint[] points, SKSize itemSize, float origin, float headerHeight) { if (points.Length > 0) { for (int i = 0; i < Entries.Count(); i++) { var entry = Entries.ElementAt(i); var point = points[i]; using (var paint = new SKPaint { Style = SKPaintStyle.Fill, Color = entry.Color, }) { var x = point.X - (itemSize.Width / 2); var y = Math.Min(origin, point.Y); var height = Math.Max(MinBarHeight, Math.Abs(origin - point.Y)); if (height < MinBarHeight) { height = MinBarHeight; if (y + height > Margin + itemSize.Height) { y = headerHeight + itemSize.Height - height; } } var rect = SKRect.Create(x, y, itemSize.Width, height); canvas.DrawRect(rect, paint); } } } }
public override void TapCanvas(SKPoint locationTapped) { base.TapCanvas(locationTapped); if (IsTooltipEnabled) { for (int i = 0; i < EntriesPoints.Length; i++) { SKPoint point = (SKPoint)EntriesPoints[i]; var distance = Math.Pow(point.X - locationTapped.X, 2) + Math.Pow(point.Y - locationTapped.Y, 2); if (distance <= Math.Pow(_touchRadius, 2)) { if (_tooltipPoint != point) { TouchedEntry = Entries.ElementAt(i); _shouldDrawTooltip = true; _tooltipPoint = point; return; } } } } _shouldDrawTooltip = false; _tooltipPoint = default; TouchedEntry = null; }
private void CheckForDoubleUnderscoresInsideSingle() { var openingTag = ParserTags["_"][TagType.Opening]; var closingTag = ParserTags["_"][TagType.Closing]; var regexp = new Regex(openingTag + ".*" + closingTag); var results = regexp.Matches(Markdown); if (results.Count == 0) { return; } for (var position = 0; position < Entries.Keys.Count; position += 2) { var openingUnderscoreIndex = Entries.ElementAt(position).Key; var closingUnderscoreIndex = Entries.ElementAt(position + 1).Key; foreach (var result in results) { var match = result as Match; var startIndex = match.Index; var lastIndex = startIndex + match.Length - 1; if (startIndex > openingUnderscoreIndex || lastIndex < closingUnderscoreIndex) { continue; } Entries.Remove(openingUnderscoreIndex); Entries.Remove(closingUnderscoreIndex); } } }
/// <summary> /// Рисуем лэйблы /// </summary> protected void DrawLabels(SKCanvas canvas, SKPoint[] points, SKSize itemSize, int height, float footerHeight) { // Проходим по записям диаграммы for (var i = 0; i < Entries.Count(); i++) { // Получаем запись var entry = Entries.ElementAt(i); var point = points[i]; // Если лейбл не пустой if (!string.IsNullOrEmpty(entry.Label)) { using (var paint = new SKPaint()) { // Настраиваем свойства рисования paint.TextSize = GreenChartLabelTextSize; paint.IsAntialias = true; paint.Color = entry.TextColor; paint.IsStroke = false; // Отступы var bounds = new SKRect(); // Текст var text = entry.Label; // Измеряем текст paint.MeasureText(text, ref bounds); // Рисуем текст canvas.DrawText(text, point.X - (bounds.Width / 2), height - Margin + (GreenChartLabelTextSize / 2), paint); } } } }
private void ScreenInsideTags() { var finalString = new StringBuilder(Markdown); for (var i = 0; i < Entries.Count; i += 2) { foreach (var symbol in allSpecialSymbols) { var offset = 0; var regexpr = new Regex($@"(?<!\\|{symbol})({symbol})(?:[\p{{P}}\w\s-[{symbol}]])+?(?<!\\)({symbol})"); var results = regexpr.Matches(finalString.ToString(), Entries.ElementAt(i).Key); foreach (var result in results) { var match = result as Match; finalString.Insert(match.Groups[1].Index + offset, "\\"); finalString.Insert(match.Groups[2].Index + offset + 1, "\\"); offset += 2; } } } Entries.Clear(); Screens.Clear(); Markdown = finalString.ToString(); insideTagsScreened = true; FillEntries(); }
private void DrawCaptionLeftAndRight(SKCanvas canvas, int width, int height, bool isGraphCentered) { var sumValue = Entries.Sum(x => Math.Abs(x.Value)); var rightValues = new List <ChartEntry>(); var leftValues = new List <ChartEntry>(); int i = 0; var current = 0.0f; while (i < Entries.Count() && (current < sumValue / 2)) { var entry = Entries.ElementAt(i); rightValues.Add(entry); current += Math.Abs(entry.Value); i++; } while (i < Entries.Count()) { var entry = Entries.ElementAt(i); leftValues.Add(entry); i++; } leftValues.Reverse(); DrawCaptionElements(canvas, width, height, rightValues, false, isGraphCentered); DrawCaptionElements(canvas, width, height, leftValues, true, isGraphCentered); }
protected void DrawLabels(SKCanvas canvas, SKPoint[] points, SKSize itemSize, int height, float footerHeight) { for (int i = 0; i < Entries.Count(); i++) { var entry = Entries.ElementAt(i); var point = points[i]; if (!string.IsNullOrEmpty(entry.Label)) { using (var paint = new SKPaint()) { paint.TextSize = GreenChartLabelTextSize; paint.IsAntialias = true; paint.Color = entry.TextColor; paint.IsStroke = false; var bounds = new SKRect(); var text = entry.Label; paint.MeasureText(text, ref bounds); canvas.DrawText(text, point.X - (bounds.Width / 2), height - Margin + (GreenChartLabelTextSize / 2), paint); } } } }
void DrawCaption(SKCanvas canvas, int width, int height) { var sumValue = Entries.Sum(x => Math.Abs(x.Value)); var rightValues = new List <Entry>(); var leftValues = new List <Entry>(); var i = 0; var current = 0.0f; while (i < Entries.Count() && (current < sumValue / 2)) { var entry = Entries.ElementAt(i); rightValues.Add(entry); current += Math.Abs(entry.Value); i++; } while (i < Entries.Count()) { var entry = Entries.ElementAt(i); leftValues.Add(entry); i++; } leftValues.Reverse(); DrawCaptionElements(canvas, width, height, rightValues, false); DrawCaptionElements(canvas, width, height, leftValues, true); }
public override void DrawContent(SKCanvas canvas, int width, int height) { DrawCaption(canvas, width, height); using (new SKAutoCanvasRestore(canvas)) { canvas.Translate(width / 2, height / 2); var sumValue = Entries.Sum(x => Math.Abs(x.Value)); var radius = (Math.Min(width, height) - (2 * Margin)) / 2; var start = 0.0f; for (var i = 0; i < Entries.Count(); i++) { var entry = Entries.ElementAt(i); var end = start + (Math.Abs(entry.Value) / sumValue); var path = RadialHelpers.CreateSectorPath(start, end, radius, radius - HoleRadius); using (var paint = new SKPaint { Style = SKPaintStyle.Fill, Color = entry.Color, IsAntialias = true, }) { canvas.DrawPath(path, paint); } start = end; } } }
public override void DrawContent(SKCanvas canvas, int width, int height) { if (Entries != null) { var sumValue = Entries.Where(x => x.Value.HasValue).Sum(x => Math.Abs(x.Value.Value)); var radius = (Math.Min(width, height) - (2 * Margin)) / 2; var cx = width / 2; var cy = height / 2; var lineWidth = (LineSize < 0) ? (radius / ((Entries.Count() + 1) * 2)) : LineSize; var radiusSpace = lineWidth * 2; for (int i = 0; i < Entries.Count(); i++) { var entry = Entries.ElementAt(i); //Skip the ring if it has a null value if (!entry.Value.HasValue) { continue; } var entryRadius = (i + 1) * radiusSpace; DrawGaugeArea(canvas, entry, entryRadius, cx, cy, lineWidth); DrawGauge(canvas, entry.Color, entry.Value.Value, entryRadius, cx, cy, lineWidth); } //Make sure captions draw on top of chart DrawCaption(canvas, width, height); } }
public void SetCurrentSelectedEntry(int index) { if (!Entries.Any()) { return; } CurrentSelectedEntry = Entries.ElementAt(index); }
protected void DrawPoints(SKCanvas canvas, SKPoint[] points) { if (points.Length > 0 && PointMode != PointMode.None) { for (int i = 0; i < points.Length; i++) { var entry = Entries.ElementAt(i); var point = points[i]; canvas.DrawPoint(point, entry.Color, PointSize, PointMode); } } }
public override void DrawContent(SKCanvas canvas, int width, int height) { if (Entries != null) { DrawCaption(canvas, width, height); using (new SKAutoCanvasRestore(canvas)) { if (DrawDebugRectangles) { using (var paint = new SKPaint { Color = SKColors.Red, IsStroke = true, }) { canvas.DrawRect(DrawableChartArea, paint); } } canvas.Translate(DrawableChartArea.Left + DrawableChartArea.Width / 2, height / 2); var sumValue = Entries.Where(x => x.Value.HasValue).Sum(x => Math.Abs(x.Value.Value)); var radius = (Math.Min(DrawableChartArea.Width, DrawableChartArea.Height) - (2 * Margin)) / 2; var start = 0.0f; for (int i = 0; i < Entries.Count(); i++) { var entry = Entries.ElementAt(i); if (!entry.Value.HasValue) { continue; } var end = start + ((Math.Abs(entry.Value.Value) / sumValue) * AnimationProgress); // Sector var path = RadialHelpers.CreateSectorPath(start, end, radius, radius * HoleRadius); using (var paint = new SKPaint { Style = SKPaintStyle.Fill, Color = entry.Color, IsAntialias = true, }) { canvas.DrawPath(path, paint); } start = end; } } } }
protected void DrawArea(SKCanvas canvas, SKPoint[] points, SKSize itemSize, float origin) { if (LineAreaAlpha > 0 && points.Length > 1) { using (var paint = new SKPaint { Style = SKPaintStyle.Fill, Color = SKColors.White, IsAntialias = true, }) { using (var shaderX = CreateXGradient(points, (byte)(LineAreaAlpha * AnimationProgress))) using (var shaderY = CreateYGradient(points, (byte)(LineAreaAlpha * AnimationProgress))) { paint.Shader = EnableYFadeOutGradient ? SKShader.CreateCompose(shaderY, shaderX, SKBlendMode.SrcOut) : shaderX; var path = new SKPath(); path.MoveTo(points.First().X, origin); path.LineTo(points.First()); var last = (LineMode == LineMode.Spline) ? points.Length - 1 : points.Length; for (int i = 0; i < last; i++) { var entry = Entries.ElementAt(i); if (LineMode == LineMode.Spline) { var nextEntry = Entries.ElementAt(i + 1); var cubicInfo = CalculateCubicInfo(points, i, itemSize); path.CubicTo(cubicInfo.control, cubicInfo.nextControl, cubicInfo.nextPoint); } else if (LineMode == LineMode.Straight) { if (!entry.Value.HasValue) { continue; } path.LineTo(points[i]); } } path.LineTo(points.Last().X, origin); path.Close(); canvas.DrawPath(path, paint); } } } }
protected void DrawPoints(SKCanvas canvas, SKPoint[] points) { if (points.Length > 0 && PointMode != PointMode.None) { for (int i = 0; i < points.Length; i++) { var entry = Entries.ElementAt(i); var point = points[i]; // TO DO - Fix this throw new NotImplementedException(); // canvas.DrawPoint(point, entry.Color, PointSize, PointMode); } } }
protected SKPoint[] CalculatePoints(SKSize itemSize, float origin, float headerHeight) { var result = new List <SKPoint>(); for (int i = 0; i < Entries.Count(); i++) { var entry = Entries.ElementAt(i); var x = Margin + (itemSize.Width / 2) + (i * (itemSize.Width + Margin)); var y = headerHeight + (((MaxValue - entry.Value) / ValueRange) * itemSize.Height); var point = new SKPoint(x, y); result.Add(point); } return(result.ToArray()); }
protected void DrawLine(SKCanvas canvas, SKPoint[] points, SKSize itemSize) { if (points.Length > 1 && LineMode != LineMode.None) { using (var paint = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.White, StrokeWidth = LineSize, IsAntialias = true, }) { using (var shader = CreateXGradient(points)) { paint.Shader = shader; var path = new SKPath(); path.MoveTo(points.First()); var last = (LineMode == LineMode.Spline) ? points.Length - 1 : points.Length; for (int i = 0; i < last; i++) { var entry = Entries.ElementAt(i); if (LineMode == LineMode.Spline) { var nextEntry = Entries.ElementAt(i + 1); var cubicInfo = CalculateCubicInfo(points, i, itemSize); path.CubicTo(cubicInfo.control, cubicInfo.nextControl, cubicInfo.nextPoint); } else if (LineMode == LineMode.Straight) { if (!entry.Value.HasValue) { continue; } path.LineTo(points[i]); } } canvas.DrawPath(path, paint); } } } }
public IEnumerable <CASCFile> GetFiles(IEnumerable <int> selection = null, bool recursive = true) { if (selection != null) { foreach (int index in selection) { var entry = Entries.ElementAt(index); if (entry.Value is CASCFile) { yield return(entry.Value as CASCFile); } else { if (recursive) { foreach (var file in (entry.Value as CASCFolder).GetFiles()) { yield return(file); } } } } } else { foreach (var entry in Entries) { if (entry.Value is CASCFile) { yield return(entry.Value as CASCFile); } else { if (recursive) { foreach (var file in (entry.Value as CASCFolder).GetFiles()) { yield return(file); } } } } } }
/// <summary> /// Рисуем точечные области /// </summary> protected void DrawPointAreas(SKCanvas canvas, SKPoint[] points, float origin) { if (points.Length > 0) { for (var i = 0; i < points.Length; i++) { var entry = Entries.ElementAt(i); var point = points[i]; var y = Math.Min(origin, point.Y); using (var paint = new SKPaint { Style = SKPaintStyle.Fill, Color = entry.Color }) { var height = Math.Max(2, Math.Abs(origin - point.Y)); canvas.DrawRect(SKRect.Create(point.X - (PointSize / 2), y, PointSize, height), paint); } } } }
/// <summary> /// Draws the bar background areas. /// </summary> /// <param name="canvas">The output canvas.</param> /// <param name="points">The entry points.</param> /// <param name="itemSize">The item size.</param> /// <param name="headerHeight">The header height.</param> protected void BuildBarAreas(ICanvas canvas, Point[] points, Size itemSize, double headerHeight) { if (points.Length > 0 && PointAreaAlpha > 0) { for (int i = 0; i < points.Length; i++) { var entry = Entries.ElementAt(i); var point = points[i]; var color = entry.Color.WithA((byte)(this.BarAreaAlpha * this.AnimationProgress)); var brush = SolidColorBrush().Color(color); var max = entry.Value > 0 ? headerHeight : headerHeight + itemSize.Height; var height = Math.Abs(max - point.Y); var y = Math.Min(max, point.Y); var barArea = Rectangle().Width(itemSize.Width).Height(height).Fill(brush); canvas.Add(point.X - (itemSize.Width / 2), y, barArea); } } }
/// <summary> /// Посчитать точки /// </summary> protected SKPoint[] CalculatePoints(SKSize itemSize, float origin, float headerHeight) { // Результат var result = new List <SKPoint>(); // Проходим по записям диаграммы for (var i = 0; i < Entries.Count(); i++) { // Получаем запись var entry = Entries.ElementAt(i); // Подсчитываем x, y var x = Margin + (itemSize.Width / 2) + (i * (itemSize.Width + Margin)); var y = headerHeight + (((MaxValue - entry.Value) / ValueRange) * itemSize.Height); var point = new SKPoint(x, y); result.Add(point); } return(result.ToArray()); }
public override void DrawContent(SKCanvas canvas, int width, int height) { if (Entries != null) { DrawCaption(canvas, width, height); var sumValue = Entries.Sum(x => Math.Abs(x.Value)); var radius = (Math.Min(width, height) - (2 * Margin)) / 2; var cx = width / 2; var cy = height / 2; var lineWidth = (LineSize < 0) ? (radius / ((Entries.Count() + 1) * 2)) : LineSize; var radiusSpace = lineWidth * 2; for (int i = 0; i < Entries.Count(); i++) { var entry = Entries.ElementAt(i); var entryRadius = (i + 1) * radiusSpace; DrawGaugeArea(canvas, entry, entryRadius, cx, cy, lineWidth); DrawGauge(canvas, entry, entryRadius, cx, cy, lineWidth); } } }
/// <summary> /// Draws the bar background areas. /// </summary> /// <param name="canvas">The output canvas.</param> /// <param name="points">The entry points.</param> /// <param name="itemSize">The item size.</param> /// <param name="headerHeight">The header height.</param> protected void DrawBarAreas(SKCanvas canvas, SKPoint[] points, SKSize itemSize, float headerHeight) { if (points.Length > 0 && BarAreaAlpha > 0) { for (int i = 0; i < points.Length; i++) { var entry = Entries.ElementAt(i); var point = points[i]; using (var paint = new SKPaint { Style = SKPaintStyle.Fill, Color = entry.Color.WithAlpha((byte)(this.BarAreaAlpha * this.AnimationProgress)), }) { var max = entry.Value > 0 ? headerHeight : headerHeight + itemSize.Height; var height = Math.Abs(max - point.Y); var y = Math.Min(max, point.Y); canvas.DrawRect(SKRect.Create(point.X - (itemSize.Width / 2), y, itemSize.Width, height), paint); } } } }
public override void DrawContent(SKCanvas canvas, int width, int height) { base.DrawContent(canvas, width, height); if (AreaEntries != null) { var fromEntries = AreaEntries.Select(ae => new ChartEntry(ae.FromValue) { Color = ae.Color }); var toEntries = AreaEntries.Select(ae => new ChartEntry(ae.ToValue) { Color = ae.Color }); var fromEntriesPoints = CalculatePoints(ItemSize, Origin, HeaderHeight, fromEntries, YAxisXShift); var toEntriesPoints = CalculatePoints(ItemSize, Origin, HeaderHeight, toEntries, YAxisXShift); if (ShouldDrawAreaPoints) { DrawPoints(canvas, fromEntriesPoints, fromEntries); DrawPoints(canvas, toEntriesPoints, toEntries); } this.DrawArea(canvas, fromEntriesPoints, ItemSize, Origin, fromEntries, toEntriesPoints); this.DrawLine(canvas, fromEntriesPoints, ItemSize, fromEntries); this.DrawLine(canvas, toEntriesPoints, ItemSize, toEntries); } if (_shouldDrawTooltip) { int pointForDrawingIndex = Array.IndexOf(EntriesPoints, _tooltipPoint); if (pointForDrawingIndex >= 0) { DrawTooltip(canvas, Entries.ElementAt(pointForDrawingIndex)); } } }
public override void DrawContent(SKCanvas canvas, int width, int height) { var total = Entries?.Count() ?? 0; if (total > 0) { var captionHeight = Entries.Max(x => { var result = 0.0f; var hasLabel = !string.IsNullOrEmpty(x.Label); var hasValueLabel = !string.IsNullOrEmpty(x.ValueLabel); if (hasLabel || hasValueLabel) { var hasOffset = hasLabel && hasValueLabel; var captionMargin = LabelTextSize * 0.60f; var space = hasOffset ? captionMargin : 0; if (hasLabel) { result += LabelTextSize; } if (hasValueLabel) { result += LabelTextSize; } } return(result); }); var center = new SKPoint(width / 2, height / 2); var radius = ((Math.Min(width, height) - (2 * Margin)) / 2) - captionHeight; var rangeAngle = (float)((Math.PI * 2) / total); var startAngle = (float)Math.PI; DrawBorder(canvas, center, radius); using (var clip = new SKPath()) { clip.AddCircle(center.X, center.Y, radius); for (int i = 0; i < total; i++) { var angle = startAngle + (rangeAngle * i); var entry = Entries.ElementAt(i); int nextIndex = (i + 1) % total; var nextAngle = startAngle + (rangeAngle * nextIndex); var nextEntry = Entries.ElementAt(nextIndex); while (!nextEntry.Value.HasValue) { nextIndex = (nextIndex + 1) % total; nextAngle = startAngle + (rangeAngle * nextIndex); nextEntry = Entries.ElementAt(nextIndex); } canvas.Save(); if (entry.Value.HasValue) { var point = GetPoint(entry.Value.Value * AnimationProgress, center, angle, radius); var nextPoint = GetPoint(nextEntry.Value.Value * AnimationProgress, center, nextAngle, radius); canvas.ClipPath(clip); // Border center bars using (var paint = new SKPaint() { Style = SKPaintStyle.Stroke, StrokeWidth = BorderLineSize, Color = BorderLineColor, IsAntialias = true, }) { var borderPoint = GetPoint(MaxValue, center, angle, radius); canvas.DrawLine(point.X, point.Y, borderPoint.X, borderPoint.Y, paint); } // Values points and lines using (var paint = new SKPaint() { Style = SKPaintStyle.Stroke, StrokeWidth = BorderLineSize, Color = entry.Color.WithAlpha((byte)(entry.Color.Alpha * 0.75f * AnimationProgress)), PathEffect = SKPathEffect.CreateDash(new[] { BorderLineSize, BorderLineSize * 2 }, 0), IsAntialias = true, }) { var amount = Math.Abs(entry.Value.Value - AbsoluteMinimum) / ValueRange; canvas.DrawCircle(center.X, center.Y, radius * amount, paint); } canvas.DrawGradientLine(center, entry.Color.WithAlpha(0), point, entry.Color.WithAlpha((byte)(entry.Color.Alpha * 0.75f)), LineSize); canvas.DrawGradientLine(point, entry.Color, nextPoint, nextEntry.Color, LineSize); canvas.DrawPoint(point, entry.Color, PointSize, PointMode); } canvas.Restore(); // Labels var labelPoint = new SKPoint(0, radius + LabelTextSize + (PointSize / 2)); var rotation = SKMatrix.CreateRotation(angle); labelPoint = center + rotation.MapPoint(labelPoint); var alignment = SKTextAlign.Left; if ((Math.Abs(angle - (startAngle + Math.PI)) < Epsilon) || (Math.Abs(angle - Math.PI) < Epsilon)) { alignment = SKTextAlign.Center; } else if (angle > (float)(startAngle + Math.PI)) { alignment = SKTextAlign.Right; } canvas.DrawCaptionLabels(entry.Label, entry.TextColor, entry.ValueLabel, entry.Color.WithAlpha((byte)(255 * AnimationProgress)), LabelTextSize, labelPoint, alignment, base.Typeface, out var _); } } } }
public override void BuildContent(ICanvas canvas, int width, int height) { var total = Entries?.Count() ?? 0; if (total > 0) { var captionHeight = Entries.Max(x => { var result = 0.0; var hasLabel = !string.IsNullOrEmpty(x.Label); var hasValueLabel = !string.IsNullOrEmpty(x.ValueLabel); if (hasLabel || hasValueLabel) { var hasOffset = hasLabel && hasValueLabel; var captionMargin = LabelTextSize * 0.60f; var space = hasOffset ? captionMargin : 0; if (hasLabel) { result += LabelTextSize; } if (hasValueLabel) { result += LabelTextSize; } } return(result); }); var center = new Point(width / 2, height / 2); var radius = ((Math.Min(width, height) - (2 * Margin)) / 2) - captionHeight; var rangeAngle = (float)((Math.PI * 2) / total); var startAngle = (float)Math.PI; var nextEntry = Entries.First(); var nextAngle = startAngle; var nextPoint = GetPoint(nextEntry.Value * AnimationProgress, center, nextAngle, radius); DrawBorder(canvas, center, radius); #if LATER clip.AddCircle(center.X, center.Y, radius); #endif for (int i = 0; i < total; i++) { var angle = nextAngle; var entry = nextEntry; var point = nextPoint; var nextIndex = (i + 1) % total; nextAngle = startAngle + (rangeAngle * nextIndex); nextEntry = Entries.ElementAt(nextIndex); nextPoint = GetPoint(nextEntry.Value * AnimationProgress, center, nextAngle, radius); #if LATER canvas.Save(); canvas.ClipPath(clip); #endif // Border center bars var borderPoint = GetPoint(MaxValue, center, angle, radius); var line = Line().X1(point.X).Y1(point.Y).X2(borderPoint.X).Y2(borderPoint.Y).Stroke(SolidColorBrush().Color(BorderLineColor)).StrokeThickness(BorderLineSize); canvas.Add(0, 0, line); // Values points and lines //PathEffect = SKPathEffect.CreateDash(new[] { BorderLineSize, BorderLineSize * 2 }, 0), var amount = Math.Abs(entry.Value - AbsoluteMinimum) / ValueRange; var diameter = radius * amount * 2; var circleColor = entry.Color.WithA((byte)(entry.Color.A * 0.75f * AnimationProgress)); var circle = Ellipse().Width(diameter).Height(diameter).Stroke(SolidColorBrush().Color(circleColor)).StrokeThickness(BorderLineSize); canvas.Add(center.X - diameter / 2, center.Y - diameter / 2, circle); canvas.DrawGradientLine(center, entry.Color.WithA(0), point, entry.Color.WithA((byte)(entry.Color.A * 0.75f)), LineSize); canvas.DrawGradientLine(point, entry.Color, nextPoint, nextEntry.Color, LineSize); canvas.DrawPoint(point, entry.Color, (float)PointSize, PointMode); } #if LATER canvas.Restore(); #endif #if LATER // Labels var labelPoint = new Point(0, radius + LabelTextSize + (PointSize / 2)); var rotation = SKMatrix.MakeRotation(angle); labelPoint = center + rotation.MapPoint(labelPoint); var alignment = SKTextAlign.Left; if ((Math.Abs(angle - (startAngle + Math.PI)) < Epsilon) || (Math.Abs(angle - Math.PI) < Epsilon)) { alignment = SKTextAlign.Center; } else if (angle > (float)(startAngle + Math.PI)) { alignment = SKTextAlign.Right; } canvas.DrawCaptionLabels(entry.Label, entry.TextColor, UnicodeMode, UnicodeLanguage, entry.ValueLabel, entry.Color.WithA((byte)(255 * AnimationProgress)), LabelTextSize, labelPoint, alignment, base.Typeface, out var _); #endif } }