Loading...
Data is the most fundamental part of creating charts. F2 requires data sources to be in JSON array format, where each element is a standard JSON object.
F2's basic data format is a JSON array:
const data = [{ year: 2010, sales: 40 },{ year: 2011, sales: 30 },{ year: 2012, sales: 50 },{ year: 2013, sales: 60 },{ year: 2014, sales: 70 },{ year: 2015, sales: 80 },{ year: 2016, sales: 80 },{ year: 2017, sales: 90 },{ year: 2018, sales: 120 },];
Using data:
<Canvas context={context}><Chart data={data}><Line x="year" y="sales" /><Point x="year" y="sales" /><Tooltip /></Chart></Canvas>
| Requirement | Description |
|---|---|
| Array Format | Data source must be an array |
| Object Elements | Array elements must be objects |
| Field Names | Object keys serve as field names for mapping to chart properties |
| Field Values | Supports string, number, array, date, and other types |
When drawing a pie chart, each record in the dataset must include a constant field (and must be of string type):
const data = [{ name: 'Movie A', percent: 0.4, a: '1' },{ name: 'Movie B', percent: 0.2, a: '1' },{ name: 'Movie C', percent: 0.18, a: '1' },{ name: 'Movie D', percent: 0.15, a: '1' },{ name: 'Movie E', percent: 0.05, a: '1' },{ name: 'Others', percent: 0.02, a: '1' },];<Chart data={data} coord={{ type: 'polar' }}><Interval x="a" y="percent" color="name" coord="polar" /></Chart>
Why is a constant field needed?
Pie charts use polar coordinate systems where all data needs to be mapped to the same angular range. The constant field (e.g., a: '1') ensures all data points share the same angular starting position.
When data on the x-axis or y-axis is an array, it will automatically be mapped to an interval, creating an interval bar chart:
const data = [{ x: 'Category 1', y: [76, 100] },{ x: 'Category 2', y: [56, 108] },{ x: 'Category 3', y: [38, 129] },{ x: 'Category 4', y: [58, 155] },{ x: 'Category 5', y: [45, 120] },{ x: 'Category 6', y: [23, 99] },{ x: 'Category 7', y: [18, 56] },{ x: 'Category 8', y: [18, 34] },];<Chart data={data}><Interval x="x" y="y" /></Chart>
The array represents the minimum and maximum values of the interval: [minimum, maximum]
Candlestick charts require open, close, highest, and lowest prices, using array format:
const data = [{ date: '2023-01', value: [100, 110, 95, 120] }, // [open, close, lowest, highest]{ date: '2023-02', value: [110, 105, 100, 115] },{ date: '2023-03', value: [105, 120, 102, 125] },];<Chart data={data}><Axis field="date" type="timeCat" /><Candlestick x="date" y="value" /></Chart>
Array format: [open, close, lowest, highest]
open - Opening priceclose - Closing pricelowest - Lowest pricehighest - Highest priceScatter plots can include additional dimensions (such as size):
const data = [{ x: 10, y: 20, size: 5, category: 'A' },{ x: 15, y: 25, size: 10, category: 'B' },{ x: 20, y: 18, size: 8, category: 'A' },];<Chart data={data}><Point x="x" y="y" size="size" color="category" /></Chart>
Before passing to Chart, you can use JavaScript array methods to filter data:
const rawData = [{ year: 2010, sales: 40, category: 'A' },{ year: 2011, sales: 30, category: 'B' },{ year: 2012, sales: 50, category: 'A' },{ year: 2013, sales: 60, category: 'B' },];// Keep only data where category is 'A'const data = rawData.filter(item => item.category === 'A');<Chart data={data}><Line x="year" y="sales" /></Chart>
const rawData = [{ name: 'A', value: 30 },{ name: 'B', value: 50 },{ name: 'C', value: 20 },];// Sort by value in descending orderconst data = [...rawData].sort((a, b) => b.value - a.value);<Chart data={data}><Interval x="name" y="value" /></Chart>
const rawData = [{ category: 'A', value: 10 },{ category: 'A', value: 20 },{ category: 'B', value: 30 },{ category: 'B', value: 40 },];// Aggregate by category (sum)const aggregated = {};rawData.forEach(item => {if (!aggregated[item.category]) {aggregated[item.category] = 0;}aggregated[item.category] += item.value;});const data = Object.entries(aggregated).map(([category, value]) => ({category,value,}));// Result: [{ category: 'A', value: 30 }, { category: 'B', value: 70 }]
const rawData = [{ date: '2023-01-01', value: 100 },{ date: '2023-02-01', value: 120 },];// Transform date formatconst data = rawData.map(item => ({...item,date: new Date(item.date),// Or add computed fieldsvalueFormatted: item.value.toFixed(2),}));
F2 supports dynamic data updates with animated transitions:
let chart = null;// Initial dataconst data1 = [{ genre: 'Sports', sold: 275 },{ genre: 'Strategy', sold: 115 },];const { props } = (<Canvas context={context}><Chart data={data1}><Interval x="genre" y="sold" /></Chart></Canvas>);chart = new Canvas(props);chart.render();// Update dataconst data2 = [{ genre: 'Sports', sold: 350 },{ genre: 'Strategy', sold: 200 },];const { props: newProps } = (<Canvas context={context}><Chart data={data2}><Interval x="genre" y="sold" /></Chart></Canvas>);chart.update(newProps); // Automatically triggers animation
// Display empty state when data is emptyconst data = [];if (data.length === 0) {// Show empty statereturn <EmptyState />;}return (<Chart data={data}><Interval x="genre" y="sold" /></Chart>);
const data = [{ year: 2010, sales: 40 },{ year: 2011, sales: null }, // Missing value{ year: 2012, sales: 50 },];// Filter out missing valuesconst cleanData = data.filter(item => item.sales != null);// Or fill with default valueconst filledData = data.map(item => ({...item,sales: item.sales ?? 0,}));
For large datasets, consider:
// Data sampling examplefunction sampleData(data, maxSize) {if (data.length <= maxSize) return data;const step = Math.ceil(data.length / maxSize);return data.filter((_, index) => index % step === 0);}const largeData = [...]; // Large datasetconst sampledData = sampleData(largeData, 1000);<Chart data={sampledData}><Line x="date" y="value" /></Chart>
import { Canvas, Chart, Interval, Axis, Tooltip } from '@antv/f2';const rawData = [{ month: 'Jan', sales: 100, profit: 20 },{ month: 'Feb', sales: 120, profit: 25 },{ month: 'Mar', sales: 90, profit: 15 },{ month: 'Apr', sales: 150, profit: 35 },{ month: 'May', sales: 180, profit: 40 },{ month: 'Jun', sales: 200, profit: 45 },];// Data processing: Add profit rate fieldconst data = rawData.map(item => ({...item,profitRate: (item.profit / item.sales * 100).toFixed(2) + '%',}));const context = document.getElementById('container').getContext('2d');const { props } = (<Canvas context={context}><Chartdata={data}scale={{sales: {min: 0,},}}><Axis field="month" /><Axis field="sales" /><Interval x="month" y="sales" color="month" /><Tooltip /></Chart></Canvas>);const canvas = new Canvas(props);canvas.render();
Constant data defined directly in code:
const data = [{ x: 1, y: 2 },{ x: 2, y: 4 },];
Fetched from remote API:
async function fetchData() {const response = await fetch('https://api.example.com/data');const data = await response.json();const { props } = (<Canvas context={context}><Chart data={data}><Interval x="category" y="value" /></Chart></Canvas>);const canvas = new Canvas(props);canvas.render();}fetchData();
Responsive to user interactions:
function updateChart(userInput) {const data = processData(userInput);const { props: newProps } = (<Canvas context={context}><Chart data={data}><Interval x="category" y="value" /></Chart></Canvas>);chart.update(newProps);}