보조지표 라벨 영역 스크롤 확대 축소 수정
This commit is contained in:
@@ -1219,7 +1219,8 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
|||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
m.zoomPriceAxisByWheel(chartX, chartY, e.deltaY);
|
const delta = Math.abs(e.deltaY) >= Math.abs(e.deltaX) ? e.deltaY : e.deltaX;
|
||||||
|
m.zoomPriceAxisByWheel(chartX, chartY, delta);
|
||||||
};
|
};
|
||||||
container.addEventListener('wheel', onWheelCapture, { capture: true, passive: false });
|
container.addEventListener('wheel', onWheelCapture, { capture: true, passive: false });
|
||||||
|
|
||||||
|
|||||||
@@ -417,7 +417,7 @@ export class ChartManager {
|
|||||||
// pressedMouseMove: TradingChart 에서 커스텀 패닝 처리 (드로잉·클릭과 충돌 방지)
|
// pressedMouseMove: TradingChart 에서 커스텀 패닝 처리 (드로잉·클릭과 충돌 방지)
|
||||||
// horzTouchDrag: 보조 pane 터치 드래그가 메인 timeScale 과 어긋나는 현상 방지 — TradingChart 커스텀 패닝만 사용
|
// horzTouchDrag: 보조 pane 터치 드래그가 메인 timeScale 과 어긋나는 현상 방지 — TradingChart 커스텀 패닝만 사용
|
||||||
handleScroll: { mouseWheel: true, pressedMouseMove: false, horzTouchDrag: false, vertTouchDrag: false },
|
handleScroll: { mouseWheel: true, pressedMouseMove: false, horzTouchDrag: false, vertTouchDrag: false },
|
||||||
handleScale: { axisPressedMouseMove: true, axisDoubleClickReset: true, mouseWheel: true, pinch: true },
|
handleScale: { axisPressedMouseMove: true, axisDoubleClickReset: true, mouseWheel: false, pinch: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
this._applyDisplayTimezoneOptions();
|
this._applyDisplayTimezoneOptions();
|
||||||
@@ -4120,15 +4120,15 @@ export class ChartManager {
|
|||||||
const paneIndex = this.getPaneIndexAtChartY(chartY);
|
const paneIndex = this.getPaneIndexAtChartY(chartY);
|
||||||
const scaleW = this.getPriceScaleWidth(paneIndex);
|
const scaleW = this.getPriceScaleWidth(paneIndex);
|
||||||
if (scaleW <= 0) return false;
|
if (scaleW <= 0) return false;
|
||||||
return chartX >= this.container.clientWidth - scaleW;
|
const minSub = this._minIndicatorSubPane();
|
||||||
|
const hitW = paneIndex >= minSub ? Math.max(scaleW, 72) : scaleW;
|
||||||
|
return chartX >= this.container.clientWidth - hitW;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** pane 우측 가격축(값 라벨) 너비 — PaneLegend 버튼 배치용 */
|
/** pane 우측 가격축(값 라벨) 너비 — PaneLegend 버튼 배치용 */
|
||||||
getPriceScaleWidth(paneIndex: number): number {
|
getPriceScaleWidth(paneIndex: number): number {
|
||||||
try {
|
try {
|
||||||
const ps = paneIndex === 1
|
const ps = this._getPriceScaleForPane(paneIndex);
|
||||||
? this.chart.priceScale('volume', 1)
|
|
||||||
: this.chart.priceScale('right', paneIndex);
|
|
||||||
const scaleW = ps.width();
|
const scaleW = ps.width();
|
||||||
return scaleW > 0 ? scaleW : 56;
|
return scaleW > 0 ? scaleW : 56;
|
||||||
} catch {
|
} catch {
|
||||||
@@ -4136,6 +4136,14 @@ export class ChartManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** pane 1 = 볼륨(표시 시) 또는 첫 보조지표(볼륨 숨김) */
|
||||||
|
private _getPriceScaleForPane(paneIndex: number) {
|
||||||
|
if (paneIndex === 1 && this._volumePaneShown()) {
|
||||||
|
return this.chart.priceScale('volume', 1);
|
||||||
|
}
|
||||||
|
return this.chart.priceScale('right', paneIndex);
|
||||||
|
}
|
||||||
|
|
||||||
/** 캔들 pane(0) 플롯 영역 너비 (우측 가격축 제외) */
|
/** 캔들 pane(0) 플롯 영역 너비 (우측 가격축 제외) */
|
||||||
private _candlePlotWidth(): number {
|
private _candlePlotWidth(): number {
|
||||||
const scaleW = this.getPriceScaleWidth(0);
|
const scaleW = this.getPriceScaleWidth(0);
|
||||||
@@ -4279,9 +4287,11 @@ export class ChartManager {
|
|||||||
|
|
||||||
/** 우측 가격축 라벨 영역 휠 — 해당 pane(캔들·거래량·보조지표) 세로 줌 */
|
/** 우측 가격축 라벨 영역 휠 — 해당 pane(캔들·거래량·보조지표) 세로 줌 */
|
||||||
zoomPriceAxisByWheel(chartX: number, chartY: number, deltaY: number): boolean {
|
zoomPriceAxisByWheel(chartX: number, chartY: number, deltaY: number): boolean {
|
||||||
if (deltaY === 0 || !this.isOnPriceAxis(chartX, chartY)) return false;
|
if (!this.isOnPriceAxis(chartX, chartY)) return false;
|
||||||
const paneIndex = this.getPaneIndexAtChartY(chartY);
|
const paneIndex = this.getPaneIndexAtChartY(chartY);
|
||||||
return this._zoomPanePriceScaleByWheel(paneIndex, deltaY, chartY);
|
const delta = deltaY !== 0 ? deltaY : 0;
|
||||||
|
if (delta === 0) return true;
|
||||||
|
return this._zoomPanePriceScaleByWheel(paneIndex, delta, chartY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -4299,24 +4309,14 @@ export class ChartManager {
|
|||||||
return this._zoomPanePriceScaleByWheel(paneIndex, deltaY, anchorChartY);
|
return this._zoomPanePriceScaleByWheel(paneIndex, deltaY, anchorChartY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getPriceScaleForPane(paneIndex: number) {
|
|
||||||
return paneIndex === 1
|
|
||||||
? this.chart.priceScale('volume', 1)
|
|
||||||
: this.chart.priceScale('right', paneIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _getRepresentativeSeriesForPane(paneIndex: number): ISeriesApi<SeriesType> | null {
|
private _getRepresentativeSeriesForPane(paneIndex: number): ISeriesApi<SeriesType> | null {
|
||||||
if (paneIndex === 0) return this.mainSeries;
|
if (paneIndex === 0) return this.mainSeries;
|
||||||
if (paneIndex === 1 && this.volumeSeries) {
|
if (paneIndex === 1 && this._volumePaneShown() && this.volumeSeries) {
|
||||||
try {
|
return this.volumeSeries;
|
||||||
const vis = (this.volumeSeries.options() as { visible?: boolean }).visible;
|
|
||||||
if (vis !== false) return this.volumeSeries;
|
|
||||||
} catch {
|
|
||||||
return this.volumeSeries;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (const entry of this.indicators.values()) {
|
for (const entry of this.indicators.values()) {
|
||||||
if (entry.paneIndex === paneIndex && entry.seriesList.length > 0) {
|
const entryPane = entry.paneIndex ?? this._readSeriesPaneIndex(entry.seriesList[0]) ?? -1;
|
||||||
|
if (entryPane === paneIndex && entry.seriesList.length > 0) {
|
||||||
return entry.seriesList[0];
|
return entry.seriesList[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4324,12 +4324,17 @@ export class ChartManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _readPanePriceRange(paneIndex: number): { from: number; to: number } | null {
|
private _snapshotPaneAutoscaleRange(paneIndex: number): { from: number; to: number } | null {
|
||||||
if (paneIndex === 0) return this._readMainPriceRange();
|
const ps = this._getPriceScaleForPane(paneIndex);
|
||||||
|
try {
|
||||||
|
const existing = ps.getVisibleRange();
|
||||||
|
if (existing) return { from: existing.from, to: existing.to };
|
||||||
|
} catch { /* fall through */ }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const existing = this._getPriceScaleForPane(paneIndex).getVisibleRange();
|
ps.setAutoScale(true);
|
||||||
if (existing) return { from: existing.from, to: existing.to };
|
const ranged = ps.getVisibleRange();
|
||||||
|
if (ranged) return { from: ranged.from, to: ranged.to };
|
||||||
} catch { /* fall through */ }
|
} catch { /* fall through */ }
|
||||||
|
|
||||||
const series = this._getRepresentativeSeriesForPane(paneIndex);
|
const series = this._getRepresentativeSeriesForPane(paneIndex);
|
||||||
@@ -4342,6 +4347,11 @@ export class ChartManager {
|
|||||||
return { from: Math.min(pTop, pBot), to: Math.max(pTop, pBot) };
|
return { from: Math.min(pTop, pBot), to: Math.max(pTop, pBot) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _readPanePriceRange(paneIndex: number): { from: number; to: number } | null {
|
||||||
|
if (paneIndex === 0) return this._readMainPriceRange();
|
||||||
|
return this._snapshotPaneAutoscaleRange(paneIndex);
|
||||||
|
}
|
||||||
|
|
||||||
private _preparePaneManualPriceScale(paneIndex: number): void {
|
private _preparePaneManualPriceScale(paneIndex: number): void {
|
||||||
if (paneIndex === 0) {
|
if (paneIndex === 0) {
|
||||||
if (!this.mainSeries) return;
|
if (!this.mainSeries) return;
|
||||||
@@ -4354,14 +4364,15 @@ export class ChartManager {
|
|||||||
this._getPriceScaleForPane(paneIndex).setAutoScale(false);
|
this._getPriceScaleForPane(paneIndex).setAutoScale(false);
|
||||||
} catch { /* ok */ }
|
} catch { /* ok */ }
|
||||||
|
|
||||||
if (paneIndex === 1 && this.volumeSeries) {
|
if (paneIndex === 1 && this._volumePaneShown() && this.volumeSeries) {
|
||||||
try {
|
try {
|
||||||
this.volumeSeries.applyOptions({ autoscaleInfoProvider: undefined });
|
this.volumeSeries.applyOptions({ autoscaleInfoProvider: undefined });
|
||||||
} catch { /* ok */ }
|
} catch { /* ok */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const entry of this.indicators.values()) {
|
for (const entry of this.indicators.values()) {
|
||||||
if (entry.paneIndex !== paneIndex) continue;
|
const entryPane = entry.paneIndex ?? this._readSeriesPaneIndex(entry.seriesList[0]) ?? -1;
|
||||||
|
if (entryPane !== paneIndex) continue;
|
||||||
for (const series of entry.seriesList) {
|
for (const series of entry.seriesList) {
|
||||||
try {
|
try {
|
||||||
series.applyOptions({ autoscaleInfoProvider: undefined });
|
series.applyOptions({ autoscaleInfoProvider: undefined });
|
||||||
|
|||||||
Reference in New Issue
Block a user