สร้าง Bubble Chart (กราฟฟองสบู่) ด้วย MPAndroidChart
Bubble Chart แสดงข้อมูล 3 มิติ: X, Y, และ Size (ขนาดฟองสบู่) เหมาะสำหรับการวิเคราะห์ข้อมูลที่มี 3 ตัวแปร เช่น (ราคา, ยอดขาย, กำไร) หรือ (GDP, ประชากร, CO2)
ขั้นตอนที่ 1: สร้างโปรเจกต์และเพิ่ม Dependency
Module build.gradle:
dependencies {
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
}
Project build.gradle: เพิ่ม maven { url 'https://jitpack.io' }
ขั้นตอนที่ 2: Layout - activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.github.mikephil.charting.charts.BubbleChart
android:id="@+id/bubbleChart"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
ขั้นตอนที่ 3: MainActivity.java - Bubble Chart พื้นฐาน
package com.example.bubblechartdemo;
import android.graphics.Color;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.github.mikephil.charting.charts.BubbleChart;
import com.github.mikephil.charting.data.BubbleData;
import com.github.mikephil.charting.data.BubbleDataSet;
import com.github.mikephil.charting.data.BubbleEntry;
import com.github.mikephil.charting.utils.ColorTemplate;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private BubbleChart bubbleChart;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bubbleChart = findViewById(R.id.bubbleChart);
setupBubbleChart();
}
private void setupBubbleChart() {
// BubbleEntry(x, y, size)
List<BubbleEntry> entries = new ArrayList<>();
entries.add(new BubbleEntry(10f, 50f, 30f)); // x=10, y=50, size=30
entries.add(new BubbleEntry(20f, 80f, 50f));
entries.add(new BubbleEntry(30f, 40f, 20f));
entries.add(new BubbleEntry(40f, 90f, 60f));
entries.add(new BubbleEntry(50f, 30f, 15f));
entries.add(new BubbleEntry(60f, 70f, 40f));
entries.add(new BubbleEntry(70f, 60f, 35f));
entries.add(new BubbleEntry(80f, 85f, 55f));
BubbleDataSet dataSet = new BubbleDataSet(entries, "ผลิตภัณฑ์");
dataSet.setColors(ColorTemplate.MATERIAL_COLORS);
dataSet.setValueTextColor(Color.WHITE);
dataSet.setValueTextSize(10f);
dataSet.setDrawValues(true);
dataSet.setValueFormatter((value, entry, dataSetIndex, viewPortHandler) -> {
BubbleEntry be = (BubbleEntry) entry;
return String.format("Size: %.0f", be.getSize());
});
// Highlight Circle
dataSet.setHighlightCircleWidth(2f);
dataSet.setHighlightColor(Color.WHITE);
BubbleData bubbleData = new BubbleData(dataSet);
bubbleChart.setData(bubbleData);
customizeBubbleChart();
}
private void customizeBubbleChart() {
bubbleChart.getDescription().setEnabled(false);
// Touch
bubbleChart.setTouchEnabled(true);
bubbleChart.setDragEnabled(true);
bubbleChart.setScaleEnabled(true);
bubbleChart.setPinchZoom(true);
// Axes
bubbleChart.getXAxis().setPosition(com.github.mikephil.charting.components.XAxis.XAxisPosition.BOTTOM);
bubbleChart.getXAxis().setGranularity(10f);
bubbleChart.getXAxis().setAxisMinimum(0f);
bubbleChart.getXAxis().setAxisMaximum(100f);
bubbleChart.getAxisLeft().setAxisMinimum(0f);
bubbleChart.getAxisLeft().setAxisMaximum(100f);
bubbleChart.getAxisRight().setEnabled(false);
// Legend
bubbleChart.getLegend().setEnabled(true);
// Animation
bubbleChart.animateXY(1500, 1500);
bubbleChart.invalidate();
}
}
BubbleEntry Parameters
new BubbleEntry(float x, float y, float size)
// x: ตำแหน่งแกน X
// y: ตำแหน่งแกน Y
// size: ขนาดฟองสบู่ (สัมพันธ์กับพื้นที่ π*r²)
// หมายเหตุ: size ไม่ใช่ radius โดยตรง แต่ MPAndroidChart คำนวณ radius = sqrt(size/π)
หลาย Series (Multiple DataSets)
// Series 1: บริษัท A
List<BubbleEntry> entriesA = new ArrayList<>();
entriesA.add(new BubbleEntry(10, 50, 30));
entriesA.add(new BubbleEntry(20, 80, 50));
// Series 2: บริษัท B
List<BubbleEntry> entriesB = new ArrayList<>();
entriesB.add(new BubbleEntry(15, 60, 25));
entriesB.add(new BubbleEntry(25, 70, 45));
BubbleDataSet setA = new BubbleDataSet(entriesA, "บริษัท A");
setA.setColor(Color.RED);
setA.setHighlightCircleWidth(2f);
BubbleDataSet setB = new BubbleDataSet(entriesB, "บริษัท B");
setB.setColor(Color.BLUE);
setB.setHighlightCircleWidth(2f);
BubbleData data = new BubbleData(setA, setB);
bubbleChart.setData(data);
การปรับแต่งขนาดฟองสบู่ (Size Scaling)
// ควบคุมขนาด Max/Min ของฟองสบู่
bubbleChart.setMaxVisibleCount(100); // จุดสูงสุดที่แสดงค่า
// ปรับ Scale ของ Size (default 1.0f)
bubbleChart.getTransformer(YAxis.AxisDependency.LEFT).setScaleX(1f);
bubbleChart.getTransformer(YAxis.AxisDependency.LEFT).setScaleY(1f);
// หรือใช้ setMaxSize() ใน DataSet (API ใหม่)
dataSet.setMaxSize(100f); // ขนาดสูงสุด
ตัวอย่างข้อมูลจริง: ประเทศ (GDP, Population, Area)
// ข้อมูลตัวอย่าง: x=GDP per capita, y=Life Expectancy, size=Population
List<BubbleEntry> countries = new ArrayList<>();
countries.add(new BubbleEntry(65000, 82, 330000000)); // USA
countries.add(new BubbleEntry(45000, 84, 126000000)); // Japan
countries.add(new BubbleEntry(10000, 76, 1400000000)); // China
countries.add(new BubbleEntry(50000, 83, 67000000)); // UK
countries.add(new BubbleEntry(2000, 70, 270000000)); // Indonesia
// ปรับ Size ให้เหมาะสม (Population มากเกินไป)
for (BubbleEntry e : countries) {
// Scale down population for visualization
float scaledSize = (float) Math.sqrt(e.getSize() / 1_000_000) * 5;
// ต้องสร้าง Entry ใหม่เพราะ BubbleEntry immutable
}
Bubble Chart vs Scatter Chart
| คุณสมบัติ | Scatter Chart | Bubble Chart |
|---|---|---|
| มิติข้อมูล | 2 มิติ (X, Y) | 3 มิติ (X, Y, Size) |
| Entry Class | Entry | BubbleEntry |
| การแสดงขนาด | คงที่ | ตามค่า Size |
| ใช้เมื่อไหร่ | ความสัมพันธ์ 2 ตัวแปร | ความสัมพันธ์ 3 ตัวแปร |
สรุป
Bubble Chart ใน MPAndroidChart ใช้ BubbleEntry(x, y, size) และ BubbleDataSet แสดงข้อมูล 3 มิติได้ชัดเจน จุดสำคัญคือการ Scale Size ให้เหมาะสมกับพื้นที่ Chart และใช้สีแยก Series ชัดเจน