Skip to content

Commit 5e6e697

Browse files
committed
feat: add scatter chart and calendar component
1 parent 3808a72 commit 5e6e697

File tree

6 files changed

+173
-22
lines changed

6 files changed

+173
-22
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@fanciers/echarts-react",
3-
"version": "0.0.2",
3+
"version": "0.0.3",
44
"description": "ECharts <3 React",
55
"author": "Tmk <i@tmk.im>",
66
"keywords": [
@@ -36,7 +36,7 @@
3636
"@rsbuild/plugin-react": "^1.4.0",
3737
"@storybook/addon-docs": "^9.1.4",
3838
"@storybook/react": "^9.1.4",
39-
"@types/node": "^24.3.0",
39+
"@types/node": "^24.3.1",
4040
"@types/react": "^19.1.12",
4141
"@types/react-dom": "^19.1.9",
4242
"echarts": "^6.0.0",

pnpm-lock.yaml

Lines changed: 18 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/charts.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import React from 'react';
2-
import type { BarSeriesOption, ComposeOption, GridComponentOption } from 'echarts';
2+
import type { BarSeriesOption, ComposeOption, GridComponentOption, ScatterSeriesOption } from 'echarts';
33
import {
44
BarChart as EChartBarChart,
55
LineChart as EChartLineChart,
66
PieChart as EChartPieChart,
7+
ScatterChart as EChartScatterChart,
78
type LineSeriesOption,
89
type PieSeriesOption,
910
} from 'echarts/charts';
@@ -104,3 +105,5 @@ export const LineChart = /*#__PURE__*/ defineChart<LineSeriesOption | GridCompon
104105
]);
105106

106107
export const PieChart = /*#__PURE__*/ defineChart<PieSeriesOption>([EChartPieChart]);
108+
109+
export const ScatterChart = /*#__PURE__*/ defineChart<ScatterSeriesOption>([EChartScatterChart]);

src/components.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type {
22
BrushComponentOption,
3+
CalendarComponentOption,
34
ComposeOption,
45
DatasetComponentOption,
56
DataZoomComponentOption,
@@ -19,6 +20,7 @@ import type {
1920
} from 'echarts';
2021
import {
2122
BrushComponent,
23+
CalendarComponent,
2224
DatasetComponent,
2325
DataZoomComponent,
2426
GeoComponent,
@@ -58,6 +60,8 @@ function defineComponent<T extends ComponentOption>(ext: EChartExt) {
5860

5961
export const Brush = /*#__PURE__*/ defineComponent<BrushComponentOption>([BrushComponent]);
6062

63+
export const Calendar = /*#__PURE__*/ defineComponent<CalendarComponentOption>([CalendarComponent]);
64+
6165
export const Dataset = /*#__PURE__*/ defineComponent<DatasetComponentOption>([DatasetComponent, TransformComponent]);
6266

6367
export const DataZoom = /*#__PURE__*/ defineComponent<DataZoomComponentOption>([DataZoomComponent]);

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
export { CanvasRenderer, SVGRenderer } from 'echarts/renderers';
2-
export { BarChart, LineChart, PieChart } from './charts.js';
2+
export { BarChart, LineChart, PieChart, ScatterChart } from './charts.js';
33
export {
44
Brush,
5+
Calendar,
56
Dataset,
67
DataZoom,
78
Geo,

stories/pie.stories.tsx

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
import {
2+
Calendar,
23
Dataset,
4+
Geo,
35
Legend,
46
LineChart,
57
PieChart,
8+
ScatterChart,
69
Title,
710
Toolbox,
811
Tooltip,
912
VisualMap,
1013
echarts,
1114
} from '@fanciers/echarts-react';
1215
import type { Meta, StoryObj } from '@storybook/react';
16+
import type { PieSeriesOption } from 'echarts/charts';
1317
import React from 'react';
18+
import useSWR from 'swr';
1419

1520
const meta = {
1621
title: 'Pie',
@@ -694,6 +699,144 @@ export const DatasetDefault: Story = {
694699
},
695700
};
696701

702+
export const MapIcelandPie: Story = {
703+
name: 'Pie Charts on GEO Map',
704+
render() {
705+
const { data: geoJSON } = useSWR('https://echarts.apache.org/examples/data/asset/geo/iceland.geo.json');
706+
const [isGeoLoaded, setIsGeoLoaded] = React.useState(false);
707+
React.useEffect(() => {
708+
if (!geoJSON) return;
709+
echarts.registerMap('iceland', geoJSON);
710+
setIsGeoLoaded(true);
711+
}, [geoJSON]);
712+
713+
function randomPieSeries(center: [number, number] | string, radius: number): PieSeriesOption {
714+
const data = ['A', 'B', 'C', 'D'].map((t) => {
715+
return { value: Math.round(Math.random() * 100), name: 'Category ' + t };
716+
});
717+
return {
718+
type: 'pie',
719+
coordinateSystem: 'geo',
720+
tooltip: { formatter: '{b}: {c} ({d}%)' },
721+
label: { show: false },
722+
labelLine: { show: false },
723+
animationDuration: 0,
724+
radius,
725+
center,
726+
data,
727+
};
728+
}
729+
730+
return (
731+
<PieChart
732+
style={{ width: 480, height: 300 }}
733+
series={[
734+
randomPieSeries([-19.007740346534653, 64.1780281585128], 45),
735+
randomPieSeries([-17.204666089108912, 65.44804833928391], 25),
736+
randomPieSeries([-15.264995297029705, 64.8592208009264], 30),
737+
randomPieSeries(
738+
// it's also supported to use geo region name as center since v5.4.1
739+
+echarts.version.split('.').slice(0, 3).join('') > 540
740+
? 'Vestfirðir'
741+
: // or you can only use the LngLat array
742+
[-13, 66],
743+
30
744+
),
745+
]}
746+
>
747+
<Geo
748+
geo={
749+
isGeoLoaded
750+
? {
751+
map: 'iceland',
752+
roam: true,
753+
aspectScale: Math.cos((65 * Math.PI) / 180),
754+
// nameProperty: 'name_en', // If using en name.
755+
itemStyle: { areaColor: '#e7e8ea' },
756+
emphasis: { label: { show: false } },
757+
}
758+
: []
759+
}
760+
/>
761+
<Tooltip tooltip={{}} />
762+
<Legend legend={{}} />
763+
</PieChart>
764+
);
765+
},
766+
};
767+
768+
export const CalendarPie: Story = {
769+
name: 'Calendar Pie',
770+
render() {
771+
const cellSize: [number, number] = [80, 80];
772+
const pieRadius = 30;
773+
function getVirtualData() {
774+
const date = +echarts.time.parse('2017-02-01');
775+
const end = +echarts.time.parse('2017-03-01');
776+
const dayTime = 3600 * 24 * 1000;
777+
const data = [];
778+
for (let time = date; time < end; time += dayTime) {
779+
data.push([echarts.time.format(time, '{yyyy}-{MM}-{dd}', false), Math.floor(Math.random() * 10000)]);
780+
}
781+
return data;
782+
}
783+
const scatterData = getVirtualData();
784+
const pieSeries = scatterData.map(
785+
(item, index): PieSeriesOption => ({
786+
type: 'pie',
787+
id: `pie-${index}`,
788+
center: item[0]!,
789+
radius: pieRadius,
790+
coordinateSystem: 'calendar',
791+
label: { formatter: '{c}', position: 'inside' },
792+
data: [
793+
{ name: 'Work', value: Math.round(Math.random() * 24) },
794+
{ name: 'Entertainment', value: Math.round(Math.random() * 24) },
795+
{ name: 'Sleep', value: Math.round(Math.random() * 24) },
796+
],
797+
})
798+
);
799+
800+
return (
801+
<PieChart
802+
compose={[ScatterChart]}
803+
style={{ width: 600, height: 500 }}
804+
series={[
805+
{
806+
id: 'label',
807+
type: 'scatter',
808+
coordinateSystem: 'calendar',
809+
symbolSize: 0,
810+
label: {
811+
show: true,
812+
formatter: (params) => echarts.time.format((params.value as [string, number])[0], '{dd}', false),
813+
offset: [-cellSize[0] / 2 + 10, -cellSize[1] / 2 + 10],
814+
fontSize: 14,
815+
},
816+
data: scatterData,
817+
},
818+
...pieSeries,
819+
]}
820+
>
821+
<Tooltip tooltip={{}} />
822+
<Legend legend={{ data: ['Work', 'Entertainment', 'Sleep'], bottom: 20 }} />
823+
<Calendar
824+
calendar={{
825+
top: 'middle',
826+
left: 'center',
827+
orient: 'vertical',
828+
cellSize: cellSize,
829+
yearLabel: { show: false, fontSize: 30 },
830+
dayLabel: { margin: 20, firstDay: 1, nameMap: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] },
831+
monthLabel: { show: false },
832+
range: ['2017-02'],
833+
}}
834+
/>
835+
</PieChart>
836+
);
837+
},
838+
};
839+
697840
export const DatasetLink: Story = {
698841
name: 'Share Dataset',
699842
render() {

0 commit comments

Comments
 (0)