目次
React フックは Echarts5 コンポーネント (ts/js) をカプセル化します
eチャート
Echarts は Baidu によって開発されており、中国人の習慣により一致しています。さまざまなタイプのチャートをサポートし、インタラクティブなパフォーマンスが優れています。ドキュメントは詳細でフレンドリーです。強くお勧めします。
欠点がある
-
初心者にとっては、Echart の設定が難しく、追加の学習コストが必要になる可能性があります。
-
Echarts のカスタマイズ性により、コードが冗長になり、作業負荷と開発時間が増加する可能性があります。
-
場合によっては、大規模なデータセットをレンダリングするときに Echart が遅くなる可能性があり、パフォーマンスを向上させるために他の最適化が必要になります。
ネイティブ echart+TS
ネイティブ echats の公式ドキュメントと関数は echarts-for-react よりも完全です。
しかし、echarts-for-react は反応サポートに対してよりフレンドリーで使いやすいです。
リストチャート.tsx
import React, { useEffect, useRef, useState } from 'react';
import { List, Button} from 'antd';
import { LineChartOutlined, BarChartOutlined } from '@ant-design/icons';
import { ProCard } from '@ant-design/pro-components';
import * as echarts from "echarts";
import './ListChart.css'
import { LIST_NAME, CHART_OPTION,resize,findSubstrIdx } from '../utils/ListChartUtil';
import { ListChartStatus } from "./ListChartStatus";
const ListChart: React.FC<ListChartStatus> = ({ urlPre, proc_datas, board_name }) => {
const chartRef = useRef<HTMLDivElement>(null);
const [selectedIdx, setselectedIdx] = useState<number>(0);
const [isLine, setIsLine] = React.useState<boolean>(true);
const proc_list = new Array(proc_datas.length).fill(null).map((val, i) => {
return proc_datas[i].proc_name;
});
let chart: any = null;
useEffect(() => {
if (chartRef.current) {
chart = echarts.init(chartRef.current);
const {option,urlSufs}=getOption(proc_datas[selectedIdx])
chart.setOption(option);
resize(chart);
chart.on('click', isLine ? 'xAxis' : 'series', function (params: any) {
const clickDate= isLine ? params.value:params.seriesName;
window.open(urlPre + '/' + urlSufs[findSubstrIdx(urlSufs, clickDate)] + '/index.html', '_blank');
});
}
}, [chartRef, selectedIdx, isLine]);
const initDate_UrlSufs=(proc_data:any)=>{
let urlSufs: string[] = [];
let dates: string[] = [];
proc_data.date_list.forEach((date: string, idx: number) => {
urlSufs.push(date + '/' + proc_data.report_id_list[idx]);
dates.push(date.substring(5));
});
return {dates,urlSufs};
}
const getBarDates=(series:any)=>{
const barDatas: any = [];
LIST_NAME.forEach((_, idx) => {
if (series[idx] && series[idx].length) {
barDatas.push([LIST_NAME[idx], ...series[idx]])
}
})
return barDatas;
}
const getOption=(proc_data:any)=>{
const {dates,urlSufs}=initDate_UrlSufs(proc_data)
const series = [proc_data.avg_list, proc_data.sigma3_up_list, proc_data.sigma3_up_target_list, proc_data.sigma3_down_list, proc_data.max_list, proc_data.min_list]
let option = {
tooltip: CHART_OPTION.tooltip,
legend: CHART_OPTION.legend,
toolbox: CHART_OPTION.toolbox,
yAxis: CHART_OPTION.yAxis,
title: {
text: proc_data ? board_name + ":" + proc_data.proc_name : board_name,
subtext: "点击日期可跳转到详情报告",
},
xAxis: {
type: 'category', // 类型为分类轴
triggerEvent: true, // 是否触发鼠标事件
data: isLine ? proc_data.date_list.map((date: string, idx: number) => {
return dates[idx]
}) : null,
},
series: isLine ? LIST_NAME.map((_, idx) => {
if (series[idx] && series[idx].length) {
return {
name: LIST_NAME[idx],
type: 'line',
data: series[idx],
emphasis: {
focus: 'series'
},
}
}
}) : dates.map((_, idx) => {
return {
name: dates[idx],
type: 'bar',
event: 'click',
emphasis: {
focus: 'series'
},
}
}),
dataset: isLine ? null : {
source: [
['pref', ...dates],
...getBarDates(series)
]
},
};
return {option,urlSufs};
}
return (<ProCard layout="center" className="procard" ghost>
<ProCard colSpan={6} ghost >
<List
size="small"
bordered
className='procard-list'
dataSource={proc_list}
renderItem={(item, index) => <List.Item key={Math.random()} className={selectedIdx === index ? 'selected' :undefined }
onClick={() => setselectedIdx(index)}>
{item}</List.Item>}
/>
</ProCard>
<ProCard colSpan={18} ghost >
<div className="procard-button" >
<Button className="ant-btn" icon={<LineChartOutlined />} onClick={() => setIsLine(true)} ></Button>
<Button className="ant-btn" icon={<BarChartOutlined />} onClick={() => setIsLine(false)}></Button>
</div>
<div key={`divChart${Math.random()}`}
ref={chartRef}
className='chart'
style={
{
flex: 2,
flexDirection:"column",
height: "40vh",
paddingLeft: "1vw",
}}
></div>
</ProCard>
</ProCard>
)
}
export default ListChart;
リストチャート.css
.procard {
display: flex;
padding-top: 10px;
}
.procard-list {
overflow-y: scroll;
height: 45vh;
}
.selected {
background-color: #e6f7ff !important;
}
.procard-button{
display: flex;
justify-content: flex-end;
padding-right: 7vw;
}
ListChartUtil.tsx
export const LIST_NAME = ['avg', '3∑-up', '3∑-up-target', '3∑-down', 'max', 'min']
export const CHART_OPTION = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: "shadow"
},
},
legend: {
left: 'center',
width: '35%',
selected: {
'min': false,
'3∑-down': false,
}
},
toolbox: {
show: true,
feature: {
dataZoom: {
yAxisIndex: 'none'
},
dataView: { readOnly: false },
// magicType: { type: ['line'] },
restore: {},
saveAsImage: {}
},
right: "10%"
},
yAxis: {
type: 'value',
axisLabel: {
formatter: '{value} '
}
},
}
const dom: any = []; //所有echarts图表的数组
/**
* 当屏幕尺寸变化时,循环数组里的每一项调用resize方法来实现自适应。
* @param {*} eDom
*/
export function resize(eDom: any) {
dom.push(eDom);
window.onresize = () => {
dom.forEach((it: any) => {
it.resize();
})
};
}
export function findSubstrIdx(arr: string[], substr: string): number {
for (let i = 0; i < arr.length; i++) {
if (arr[i].indexOf(substr) !== -1) {
return i;
}
}
return -1;
}
ReactECharts
React フックは Echarts5 コンポーネント (ts/js) をカプセル化します
React+TypeScript は ECharts_react タイプスクリプトをカプセル化します echart_KzXuanCn のブログ-CSDN ブログ
比較した
D3
はデータ駆動型のドキュメントベースの JavaScript ライブラリであり、柔軟性が高くカスタマイズ可能ですが、より多くのコーディング作業が必要になります。
リチャート
D3 の強力な描画機能を利用した React カプセル化をベースにしたライブラリで、React をデータ視覚化に使いやすくします。
アドバンテージ
-
Recharts はカスタマイズ オプションの数が少ないため、使いやすいです。
-
React のライフサイクル メソッドと統合して、React アプリケーションへの追加を容易にし、Redux 状態マネージャーをサポートします。
-
軽量でメモリやCPUへの影響が少ない。
-
複数のスタイル、カスタムカラー、アニメーションをサポートします。
欠点がある
-
すべてのタイプのチャートをサポートしているわけではなく、さまざまな Echarts もサポートしていません。
-
Echartsに比べて機能が少ない
要約すると、高度にカスタマイズされたチャートを設計する必要があり、十分な開発経験がある場合は、Echarts を使用する方が便利かもしれません。一方、Recharts は、迅速かつ簡単なデータ視覚化タスクに適しており、React アプリケーションに簡単に統合できます。