import { ChartArea, ChartData, ChartOptions, ScriptableContext, } from "chart.js"; import { ChartType, DefaultDataPoint } from "chart.js/dist/types"; import { PopularChargingTime } from "./types"; import { popularChargingTimeType } from "../common/enums/dashboard"; import { POPULAR_USAGE_TIME_CHART_COLORS } from "../common/constants/dashboard"; export default class ChartJsChart< TType extends ChartType = ChartType, TData = DefaultDataPoint, TLabel = unknown > { #data: ChartData; #options: ChartOptions; private static gradient: CanvasGradient | undefined; private static width: number | undefined; private static height: number | undefined; constructor( data: ChartData, options: ChartOptions ) { this.#data = data; this.#options = options; } get data(): ChartData { return this.#data; } set data(value: ChartData) { this.#data = value; } get options(): ChartOptions { return this.#options; } set options(value: ChartOptions) { this.#options = value; } /** * Bar Chart의 색상 그라데이션을 만든다. * * @public * @param context */ static gradientColor(context: ScriptableContext<"bar">) { const chart = context.chart; const { ctx, chartArea } = chart; if (!chartArea) return; return ChartJsChart.getGradient(ctx, chartArea); } /** * 이미 생성된 그라데이션이 없거나 크기가 변경될 경우 새로운 그라데이션을 만들고 생성된 그라데이션을 캐싱한다. * * @public * @param ctx * @param chartArea */ private static getGradient( ctx: CanvasRenderingContext2D, chartArea: ChartArea ) { const chartWidth = chartArea.right - chartArea.left; const chartHeight = chartArea.bottom - chartArea.top; if ( !ChartJsChart.gradient || ChartJsChart.width !== chartWidth || ChartJsChart.height !== chartHeight ) { ChartJsChart.width = chartWidth; ChartJsChart.height = chartHeight; ChartJsChart.gradient = ctx.createLinearGradient( 0, chartArea.top, 0, chartArea.bottom ); ChartJsChart.gradient.addColorStop(0, "#00adff"); ChartJsChart.gradient.addColorStop(1, "rgba(0, 173, 255, 0.2)"); } return ChartJsChart.gradient; } /** * 대시보드의 인기시간대를 인자로 넘겨주면 type에 따라 color를 return한다. * * @public * @param list: { * data: number; * type: PopularChargingTimeType['index']; * }[] * @returns string */ static getPopularChargingTimeBgColor(list: PopularChargingTime[]) { if (list.length) { return list.map((value) => { if (popularChargingTimeType.DEFAULT.index === value.type) { return POPULAR_USAGE_TIME_CHART_COLORS.DEFAULT; } if (popularChargingTimeType.MAX.index === value.type) { return POPULAR_USAGE_TIME_CHART_COLORS.MAX; } if (popularChargingTimeType.MIN.index === value.type) { return POPULAR_USAGE_TIME_CHART_COLORS.MIN; } }); } else { return ""; } } /** * 차트의 Y축 값을 동적으로 계산할 때 사용. * * @public * @param list * @return function list에 들어가 있는 값 중 0보다 클 경우 max값 업데이트 */ static getScaleYMaxValue(list: any[] | null) { let max = 0; return () => { if (list) { list?.forEach((value) => { if (null !== value && max < value) { max = value; } }); } return max; }; } }