29
loading...
This website collects cookies to deliver better user experience
echarts-liquidfill
extension quite useful.useEffect
hook and subscribing/unsubscribing to the "resize"
event multiple times.// React-ECharts.tsx
import React, { useRef, useEffect } from "react";
import { init, getInstanceByDom } from "echarts";
import type { CSSProperties } from "react";
import type { EChartsOption, ECharts, SetOptionOpts } from "echarts";
export interface ReactEChartsProps {
option: EChartsOption;
style?: CSSProperties;
settings?: SetOptionOpts;
loading?: boolean;
theme?: "light" | "dark";
}
export function ReactECharts({
option,
style,
settings,
loading,
theme,
}: ReactEChartsProps): JSX.Element {
const chartRef = useRef<HTMLDivElement>(null);
useEffect(() => {
// Initialize chart
let chart: ECharts | undefined;
if (chartRef.current !== null) {
chart = init(chartRef.current, theme);
}
// Add chart resize listener
// ResizeObserver is leading to a bit janky UX
function resizeChart() {
chart?.resize();
}
window.addEventListener("resize", resizeChart);
// Return cleanup function
return () => {
chart?.dispose();
window.removeEventListener("resize", resizeChart);
};
}, [theme]);
useEffect(() => {
// Update chart
if (chartRef.current !== null) {
const chart = getInstanceByDom(chartRef.current);
chart.setOption(option, settings);
}
}, [option, settings, theme]); // Whenever theme changes we need to add option and setting due to it being deleted in cleanup function
useEffect(() => {
// Update chart
if (chartRef.current !== null) {
const chart = getInstanceByDom(chartRef.current);
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
loading === true ? chart.showLoading() : chart.hideLoading();
}
}, [loading, theme]);
return <div ref={chartRef} style={{ width: "100%", height: "100px", ...style }} />;
}
echarts-for-react
?
echarts-for-react
as it seems to expose more functionalities for the end user than the component implemented above. props
to ECharts API. echarts-liquidfill
extension?
liquidfill
charts. We are using the following:// utils.ts
import type { DefaultLabelFormatterCallbackParams, EChartsOption } from "echarts";
/**
* interface for LiquidFillGauge series config
*/
interface LiquidFillGaugeSeries {
name?: string;
type: "liquidFill";
data: (
| number
| {
name?: string;
value: number;
direction?: "left" | "right";
itemStyle?: {
color?: string;
opacity?: number;
};
emphasis?: {
itemStyle?: {
opacity?: number;
};
};
}
)[];
silent?: boolean;
color?: string[];
center?: string[];
radius?: string;
amplitude?: number;
waveLength?: string | number;
phase?: number | "auto";
period?: number | "auto" | ((value: number, index: number) => number);
direction?: "right" | "left";
shape?: "circle" | "rect" | "roundRect" | "triangle" | "diamond" | "pin" | "arrow" | string;
waveAnimation?: boolean;
animationEasing?: string;
animationEasingUpdate?: string;
animationDuration?: number;
animationDurationUpdate?: number;
outline?: {
show?: boolean;
borderDistance?: number;
itemStyle?: {
color?: string;
borderColor?: string;
borderWidth?: number;
shadowBlur?: number;
shadowColor?: string;
};
};
backgroundStyle?: {
color?: string;
borderWidth?: string;
borderColor?: string;
itemStyle?: {
shadowBlur?: number;
shadowColor?: string;
opacity?: number;
};
};
itemStyle?: {
opacity?: number;
shadowBlur?: number;
shadowColor?: string;
};
label?: {
show?: true;
color?: string;
insideColor?: string;
fontSize?: number;
fontWeight?: string;
formatter?: string | ((params: DefaultLabelFormatterCallbackParams) => string);
align?: "left" | "center" | "right";
baseline?: "top" | "middle" | "bottom";
position?: "inside" | "left" | "right" | "top" | "bottom" | string[];
};
emphasis?: {
itemStyle?: {
opacity?: number;
};
};
}
export interface LiquidFillGaugeOption extends Omit<EChartsOption, "series"> {
series: LiquidFillGaugeSeries;
}
ReactEChartsProps
:export interface ReactEChartsProps {
option: EChartsOption | LiquidFillGaugeOption;
style?: CSSProperties;
settings?: SetOptionOpts;
loading?: boolean;
theme?: "light" | "dark";
}
ReactECharts
component to create LiquidFillGauge
component:// LiquidFillGauge.tsx
import React from "react";
import "echarts-liquidfill";
import type { CSSProperties } from "react";
import { ReactECharts } from "../React-ECharts";
import type { LiquidFillGaugeOption } from "../utils";
export interface LiquidFillGaugeProps {
option: LiquidFillGaugeOption;
style?: CSSProperties;
}
export function LiquidFillGauge({ option, style }: LiquidFillGaugeProps): JSX.Element {
return (
<ReactECharts
option={option}
style={style}
/>
);
}
option
object, say:const option: ReactEChartsProps["option"] = {
dataset: {
source: [
["Commodity", "Owned", "Financed"],
["Commodity 1", 4, 1],
["Commodity 2", 2, 4],
["Commodity 3", 3, 6],
["Commodity 4", 5, 3],
],
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
},
legend: {
data: ["Owned", "Financed"],
},
grid: {
left: "10%",
right: "0%",
top: "20%",
bottom: "20%",
},
xAxis: {
type: "value",
},
yAxis: {
type: "category",
},
series: [
{
type: "bar",
stack: "total",
label: {
show: true,
},
},
{
type: "bar",
stack: "total",
label: {
show: true,
},
},
],
}
prop
as you would in any other component:<div>
<ReactECharts option={option} />
</div>