Skip to content

동기화된 두 차트 — syncX

둘 중 아무 차트나 드래그하거나 휠로 확대해 보라 — x축(보는 구간)이 같이 움직인다. syncX(a, b)는 xDomainChange를 서로에게 미러링하는 30줄짜리 헬퍼다, 코어 계약이 아니라 조립이다.

소스

apps/examples/src/cases/sync-x.ts — CI가 타입체크하는 실물이다.

ts
import { PlotBuilder, browserDeps } from "@finchart/dom";
import type { OHLC, Plot } from "@finchart/core";
import { candleSeries, priceFormat, syncX, timeTicks } from "@finchart/core";
import { fixtureCandles } from "./fixture";
import { chartHost } from "./stage";

export const title = "동기화된 두 차트 — syncX";
export const description =
  "둘 중 아무 차트나 드래그하거나 휠로 확대해 보라 — x축(보는 구간)이 같이 움직인다. syncX(a, b)는 xDomainChange를 서로에게 미러링하는 30줄짜리 헬퍼다, 코어 계약이 아니라 조립이다.";

function buildChart(
  parent: HTMLElement,
  name: string,
  seed: number,
  height: number,
): { plot: Plot; wrapper: HTMLElement } {
  const wrapper = document.createElement("div");
  parent.append(wrapper);

  const label = document.createElement("div");
  label.textContent = name;
  label.style.cssText = "font-size: 13px; color: #64748b; margin-bottom: 4px";
  wrapper.append(label);

  const host = chartHost(wrapper, height);
  const plot = PlotBuilder.create<OHLC>(browserDeps({ autoSize: true }))
    .setSize(wrapper.clientWidth || 900, height)
    .setAxis({
      x: { ticks: timeTicks({ timeZone: "UTC", locale: "ko" }) },
      y: { position: "right", format: priceFormat({ compact: true, locale: "ko" }) },
    })
    .build(host);

  plot.mainPane.addSeries({
    series: candleSeries(),
    data: fixtureCandles(300, seed),
    name,
  });

  return { plot, wrapper };
}

export function mount(container: HTMLElement): () => void {
  const a = buildChart(container, "BTC/KRW", 7, 240);
  const b = buildChart(container, "ETH/KRW", 13, 240);

  const unsync = syncX(a.plot, b.plot);

  return Object.assign(
    () => {
      unsync();
      a.plot.destroy();
      b.plot.destroy();
      a.wrapper.remove();
      b.wrapper.remove();
    },
    {
      requestRender: () => {
        a.plot.requestRender();
        b.plot.requestRender();
      },
    },
  );
}