실시간 차트 갱신시 화면떨림 문제 해결

This commit is contained in:
Macbook
2026-05-27 14:54:50 +09:00
parent f7aac535d8
commit 7a0af36b9b
10 changed files with 517 additions and 130 deletions
+75
View File
@@ -0,0 +1,75 @@
import type { IndicatorConfig } from '../types';
export type IndicatorChartSyncMode =
| 'none'
| 'remove-only'
| 'add-only'
| 'params-changed'
| 'reorder-only'
| 'full';
export interface IndicatorChartChange {
mode: IndicatorChartSyncMode;
removedIds: string[];
added: IndicatorConfig[];
paramsChangedIds: string[];
}
export function singleIndParamKey(i: IndicatorConfig): string {
return `${JSON.stringify(i.params)}|${(i.plots ?? []).map(p => p.id).sort().join(',')}|${i.mergedWith ?? ''}`;
}
/** 이전·현재 지표 목록 차이를 분류해 최소 갱신 경로를 선택 */
export function classifyIndicatorChartChange(
prev: IndicatorConfig[],
curr: IndicatorConfig[],
): IndicatorChartChange {
const prevMap = new Map(prev.map(i => [i.id, i]));
const currMap = new Map(curr.map(i => [i.id, i]));
const removedIds = prev.filter(i => !currMap.has(i.id)).map(i => i.id);
const added = curr.filter(i => !prevMap.has(i.id));
const paramsChangedIds: string[] = [];
for (const c of curr) {
const p = prevMap.get(c.id);
if (!p) continue;
if (singleIndParamKey(p) !== singleIndParamKey(c)) {
paramsChangedIds.push(c.id);
}
}
const empty: IndicatorChartChange = {
mode: 'none',
removedIds,
added,
paramsChangedIds,
};
if (removedIds.length === 0 && added.length === 0 && paramsChangedIds.length === 0) {
const sameSet = prev.length === curr.length
&& prev.every(p => currMap.has(p.id));
if (sameSet && prev.map(i => i.id).join(',') !== curr.map(i => i.id).join(',')) {
return { ...empty, mode: 'reorder-only' };
}
return empty;
}
if (removedIds.length > 0 && added.length === 0 && paramsChangedIds.length === 0) {
return { ...empty, mode: 'remove-only' };
}
if (added.length > 0 && removedIds.length === 0 && paramsChangedIds.length === 0) {
return { ...empty, mode: 'add-only' };
}
if (
paramsChangedIds.length > 0
&& removedIds.length === 0
&& added.length === 0
) {
return { ...empty, mode: 'params-changed' };
}
return { ...empty, mode: 'full' };
}