定制微图

时间:2018-01-09 18:15:11

标签: charts xamarin.forms

我试图获得类似于附加屏幕截图的图表。问题是,如何在图表的每个弧(70,76)中放置值?我使用Microchart库。

附带的屏幕截图来自SmartHotel360 xamarin演示应用。如果有人可以帮我指出正确的方向,那将是非常有帮助的。

enter image description here

void PopulateChart()
{
    var data = new[]
    {
        new Microcharts.Entry(50)
        {
            ValueLabel = "50",
            Color = SKColor.Parse("#104950")
        },
        new Microcharts.Entry(70)
        {
            ValueLabel = "70",
            Color = SKColor.Parse("#F7A4B9")
        },
        new Microcharts.Entry(90)
        {
            ValueLabel = "90",
            Color = SKColor.Parse("#0084b4")
        }
    };

    this.chartView.Chart = new TemperatureChart() { Entries = data };
}

using Microcharts;
using SkiaSharp;
using System;
using System.Linq;

namespace chart
{
    public class TemperatureChart : Chart
    {
        public TemperatureChart()
        {
            BackgroundColor = SKColor.Parse("#F6F1E9");
        }

        public float CaptionMargin { get; set; } = 12;

        public float LineSize { get; set; } = 18;

        public float StartAngle { get; set; } = -180;

        private float AbsoluteMinimum => Entries.Select(x => x.Value).Concat(new[] { MaxValue, MinValue, InternalMinValue ?? 0 }).Min(x => Math.Abs(x));

        private float AbsoluteMaximum => Entries.Select(x => x.Value).Concat(new[] { MaxValue, MinValue, InternalMinValue ?? 0 }).Max(x => Math.Abs(x));

        private float ValueRange => AbsoluteMaximum - AbsoluteMinimum;

        public override void DrawContent(SKCanvas canvas, int width, int 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 = Convert.ToInt32(height / 1.25);
            var lineWidth = (LineSize < 0) ? (radius / ((Entries.Count() + 1) * 2)) : LineSize;
            var radiusSpace = lineWidth * 4;

            foreach (var entry in Entries.OrderByDescending(e => e.Value))
            {
                DrawChart(canvas, entry, radiusSpace, cx, cy, lineWidth);
            }

            DrawCaption(canvas, cx, cy, radiusSpace);
        }

        public void DrawChart(SKCanvas canvas, Entry entry, float radius, int cx, int cy, float strokeWidth)
        {
            using (var paint = new SKPaint
            {
                Style = SKPaintStyle.Stroke,
                StrokeWidth = strokeWidth,
                StrokeCap = SKStrokeCap.Round,
                Color = entry.Color,
                IsAntialias = true
            })
            {
                using (SKPath path = new SKPath())
                {
                    var sweepAngle = 180 * (Math.Abs(entry.Value) - AbsoluteMinimum) / ValueRange;
                    path.AddArc(SKRect.Create(cx - radius, cy - radius, 2 * radius, 2 * radius), StartAngle, sweepAngle);
                    canvas.DrawPath(path, paint);
                }
            }
        }

        private void DrawCaption(SKCanvas canvas, int cx, int cy, float radius)
        {
            var minimum = 0;
            var medium = Math.Round(Entries.Max(e => e.Value) / 2);
            var maximum = Entries.Max(e => e.Value);

            canvas.DrawCaptionLabels(string.Empty, SKColor.Empty, $"{minimum}°", SKColors.Black, LabelTextSize, new SKPoint(cx - radius - LineSize - CaptionMargin, cy), SKTextAlign.Center);
            canvas.DrawCaptionLabels(string.Empty, SKColor.Empty, $"{medium}°", SKColors.Black, LabelTextSize, new SKPoint(cx, cy - radius - LineSize), SKTextAlign.Center);
            canvas.DrawCaptionLabels(string.Empty, SKColor.Empty, $"{maximum}°", SKColors.Black, LabelTextSize, new SKPoint(cx + radius + LineSize + CaptionMargin, cy), SKTextAlign.Center);
        }
    }
}

0 个答案:

没有答案