Xamarin.Android のドキュメント
ゾーン
コントロール > FlexChart > 機能 > ゾーン

FlexChart を使用すると、色分けされたゾーンと呼ばれる領域を作成してチャートに適用できます。この色分けされたゾーンにより、チャートにプロットされたデータポイントがいくつかの領域に分類され、ユーザーは容易にデータを読み取って理解できるようになります。ユーザーは、特定のデータポイントが属するカテゴリを簡単に特定できます。

ゾーンの作成がどのように役立つかを説明するために、最大数の学生が落ちるスコアゾーンを特定し、90人以上の学生が何人いるかを示すクラスのスコアレポートを考えます。このシナリオは FlexChart で実現できます。具体的には、顧客の回答をデータポイントとしてチャートにプロットし、プロットされたデータポイントを面グラフで色分けされたゾーンに分類します。ゾーンは線タイプのデータ系列で区切られます。

FlexChart Zones

FlexChart では、ChartSeries クラスに基づくデータ系列としてゾーンを作成できます。各ゾーンは面グラフとして作成できます。それには、 ChartType プロパティを Line に設定し、それぞれを固有の色で強調表示します。

FlexChart にゾーンを作成するには、次の手順を実行します。

  1. 新しいクラス (ZonesData) を MainActivity.cs ファイルに追加して、学生数とそのスコアを生成します。
    CS
    コードのコピー
    public class ZonesData : Java.Lang.Object
    {
        public int Number { get; set; }
        public double Score { get; set; }
    
        public ZonesData(int Number, double Score)
        {
            this.Number = Number;
            this.Score = Score;
        }
    
        // ChartPoint型のゾーンサンプルオブジェクトのリストを作成するメソッド
        public static IList<object> getZonesList(int nStudents, int nMaxPoints)
        {
            List<object> list = new List<object>();
    
            Random random = new Random();
            for (int i = 0; i < nStudents; i++)
            {
                ZonesData point = new ZonesData(i, nMaxPoints * 0.5 * (1 + random.NextDouble()));
                list.Add(point);
            }
            return list;
        }
    }
    
  2. MainActivity クラスに次のコードを追加し、OnCreate メソッドをオーバーライドしてゾーンを作成します。
    CS
    コードのコピー
    public class MainActivity : Activity
    {
        private FlexChart mChart;
    
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
    
            // 「メイン」レイアウトリソースからビューを設定する
            SetContentView(Resource.Layout.Main);
    
            // ウィジェットを初期化する
            mChart = this.FindViewById<FlexChart>(Resource.Id.flexchart);
            mChart.BindingX = "Number";
            mChart.ChartType = ChartType.Scatter;
    
            int nStudents = 20;
            int nMaxPoints = 100;
            IList<object> data = ZonesData.getZonesList(nStudents, nMaxPoints);
            mChart.ItemsSource = data;
    
            mChart.Tapped += MChart_Tapped;
            mChart.AxisX.Title = "学生数";
            mChart.AxisY.Title = "学生累積ポイント";
    
            double mean = this.FindMean(data);
            double stdDev = this.FindStdDev(data, mean);
            List<double> scores = new List<double>();
            foreach (ZonesData item in data)
            {
                scores.Add(item.Score);
            }
            scores.Sort((x, y) => y.CompareTo(x));
    
            var zones = new double[]
            {
                scores[this.GetBoundingIndex(scores, 0.85)],
                scores[this.GetBoundingIndex(scores, 0.75)],
                scores[this.GetBoundingIndex(scores, 0.25)],
                scores[this.GetBoundingIndex(scores, 0.05)]
            };
    
            Integer[] colors = new Integer[]
            {
                new Integer(Color.Argb(255,255,192,192)),
                new Integer(Color.Argb(255,55,228,228)),
                new Integer(Color.Argb(255,255,228,128)),
                new Integer(Color.Argb(255,128,255,128)),
                new Integer(Color.Argb(255,128,128,255)),
            };
            for (var i = 4; i >= 0; i--)
            {
                float y = (float)(i == 4 ? mean + 2 * stdDev : zones[i]);
                PointF[] sdata = new PointF[data.Count];
    
                for (int j = 0; j < data.Count; j++)
                {
                    sdata[j] = new PointF(j, y);
                    if (i == 0)
                    {
                        System.Console.WriteLine(j + "=" + y);
                    }
                }
    
                string seriesName = ((char)((short)'A' + 4 - i)).ToString();
    
                var series = new ChartSeries();
                series.Chart = mChart;
                series.SeriesName = seriesName;
                series.Binding = "Y";
    
                series.ItemsSource = sdata;
                series.BindingX = "X";
                series.ChartType = ChartType.Area;
                series.Style = new ChartStyle();
                series.Style.Fill = new Color(colors[i].IntValue());
    
                mChart.Series.Add(series);
            }
    
            ChartSeries scoreSeries = new ChartSeries();
            scoreSeries.Chart = mChart;
            scoreSeries.SeriesName = "生スコア";
            scoreSeries.Binding = "Score";
            mChart.Series.Add(scoreSeries);
    
            for (var i = -2; i <= 2; i++)
            {
                var y = mean + i * stdDev;
                string seriesName = string.Empty;
                if (i > 0)
                {
                    seriesName = "m+" + i + "s";
                }
                else if (i < 0)
                {
                    seriesName = "m" + i + "s";
                }
                else
                {
                    seriesName = "平均";
                }
                PointF[] sdata = new PointF[data.Count];
                for (int j = 0; j < data.Count; j++)
                {
                    sdata[j] = new PointF(j, (float)y);
                }
                var series = new ChartSeries();
                series.Chart = mChart;
                series.SeriesName = seriesName;
                series.Binding = "Y";
    
                series.ItemsSource = sdata;
                series.BindingX = "X";
                series.ChartType = ChartType.Line;
                series.Style = new ChartStyle();
                series.Style.StrokeThickness = 2;
    
                series.Style.Stroke = Color.Rgb(0x20, 0x20, 0x20);
    
                mChart.Series.Add(series);
            }
        }
    
        private double FindMean(IList<object> data)
        {
            double sum = 0;
            foreach (ZonesData item in data)
            {
                sum += item.Score;
            }
            return sum / data.Count;
        }
        private double FindStdDev(IList<object> data, double mean)
        {
            double sum = 0;
            for (var i = 0; i < data.Count; i++)
            {
                ZonesData item = (ZonesData)data[i];
                var d = item.Score - mean;
                sum += d * d;
            }
            return System.Math.Sqrt(sum / data.Count);
        }
        private int GetBoundingIndex(List<double> scores, double frac)
        {
            var n = scores.Count;
            int i = (int)System.Math.Ceiling(n * frac);
            while (i > scores[0] && scores[i] == scores[i + 1])
                i--;
            return i;
        }
        private void MChart_Tapped(object sender, C1TappedEventArgs e)
        {
            if (!mChart.ToolTip.Text.Contains("raw score"))
            {
                mChart.ToolTip.IsOpen = false;
            }
         }
    }