일목균형표 수정

This commit is contained in:
Macbook
2026-05-27 23:36:48 +09:00
parent 9cee6387c3
commit 8cc0d1c88c
73 changed files with 2256 additions and 334 deletions
@@ -0,0 +1,88 @@
import React, { useCallback, useEffect, useRef } from 'react';
import type { ChartManager } from '../utils/ChartManager';
import type { ChartPaneSeparatorOptions } from '../types/chartPaneSeparator';
import { plotColorCss } from '../utils/plotColorUtils';
interface Props {
manager: ChartManager;
options: ChartPaneSeparatorOptions;
}
function applyLineDash(ctx: CanvasRenderingContext2D, style: ChartPaneSeparatorOptions['lineStyle']) {
if (style === 'dashed') ctx.setLineDash([6, 4]);
else if (style === 'dotted') ctx.setLineDash([2, 3]);
else ctx.setLineDash([]);
}
const PaneSeparatorOverlay: React.FC<Props> = ({ manager, options }) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
const redraw = useCallback(() => {
const canvas = canvasRef.current;
const container = manager.getContainer();
if (!canvas || !container) return;
const cssW = container.clientWidth;
const cssH = container.clientHeight;
if (cssW <= 0 || cssH <= 0) return;
const dpr = window.devicePixelRatio || 1;
canvas.width = Math.round(cssW * dpr);
canvas.height = Math.round(cssH * dpr);
canvas.style.width = `${cssW}px`;
canvas.style.height = `${cssH}px`;
const ctx = canvas.getContext('2d');
if (!ctx) return;
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
ctx.clearRect(0, 0, cssW, cssH);
if (!options.visible) return;
const layouts = manager.getPaneLayouts()
.filter(l => l.height > 8)
.sort((a, b) => a.topY - b.topY);
if (layouts.length < 2) return;
ctx.strokeStyle = plotColorCss(options.color);
ctx.lineWidth = options.width;
applyLineDash(ctx, options.lineStyle);
for (let i = 0; i < layouts.length - 1; i++) {
const y = layouts[i].topY + layouts[i].height;
const lineY = y + options.width / 2;
ctx.beginPath();
ctx.moveTo(0, lineY);
ctx.lineTo(cssW, lineY);
ctx.stroke();
}
}, [manager, options]);
useEffect(() => {
redraw();
const unsub = manager.subscribePaneLayout(redraw);
const container = manager.getContainer();
const ro = new ResizeObserver(() => redraw());
if (container) ro.observe(container);
return () => {
unsub();
ro.disconnect();
};
}, [manager, redraw]);
return (
<canvas
ref={canvasRef}
className="pane-separator-overlay"
aria-hidden
style={{
position: 'absolute',
inset: 0,
pointerEvents: 'none',
zIndex: 4,
}}
/>
);
};
export default PaneSeparatorOverlay;