mcpField
L
lightweight-charts

lightweight-charts

github.com/tradingview開発17.7k1.5k 回インストール6 日前に更新
リポジトリ

lightweight-charts について

lightweight-chartsは、下流のnpmアプリと上流のソースリポジトリの両方で、lightweight-charts APIの利用を支援するスキルです。ローカルの型定義を優先して確認し、v5の使い方や移行方法を案内します。

主な機能

  1. 01ローカルの型定義に基づくAPI確認
  2. 02npm利用アプリとソースリポジトリの判別
  3. 03v5のチャート、シリーズ、ペインの説明
  4. 04時間、操作、リアルタイム更新の問題調査
  5. 05v4 APIからv5への置き換え案内

活用シーン

  1. 01インストール済みバージョンに合わせたチャートコード作成
  2. 02タイムスタンプ単位やデータ順序のデバッグ
  3. 03旧シリーズ・マーカーコードのv5移行

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/tradingview/lightweight-charts --skill lightweight-charts

インストール後、Claude Code で/lightweight-chartsを入力して読み込まれたか確認します。

詳細

Lightweight Charts スキル

プロジェクトが下流の npm 利用アプリでも、上流の lightweight-charts ソースチェックアウトでも、同じように機能します。まず、以下の手順でどちらかを判断し、ローカルで利用できる型定義からすべての API 名を確認してください。

ソースの確認順序

上流のソースリポジトリ内にいると決めつけないでください。

  1. 利用アプリでは、まずインストール済みパッケージを調べます。
    • 実際のバージョンは node_modules/lightweight-charts/package.json で確認します。
    • API の範囲は node_modules/lightweight-charts/dist/typings.d.ts で確認します。
  2. 上流リポジトリでは、まず dist/typings.d.ts を調べ、生成済みの出力がない場合は src/ を調べます。
  3. 公式ドキュメントやサンプルは補足情報として使いますが、内容が異なる場合はローカルの型定義を優先してください。

回答前に確認します(コピーして貼り付けてください)。

node -p "require('./node_modules/lightweight-charts/package.json').version"
rg -n "createSeriesMarkers|addSeries|IPrimitivePaneRenderer|createImageWatermark|createOptionsChart" node_modules/lightweight-charts/dist/typings.d.ts
# upstream checkout instead of a consumer app:
rg -n "createSeriesMarkers|IPrimitivePaneRenderer|createImageWatermark|createOptionsChart" dist/typings.d.ts src

該当するファイルが見つからない場合は、確認できなかった内容を伝えてください。オプション名、メソッド、エクスポート、ラッパーの動作を捏造しないでください。

ユーザーのコードが from lightweight_charts import ...(アンダースコア)をインポートしている、pandas/asyncio を使用している、または Python ウィンドウラッパーについて述べている場合は、TypeScript パッケージではなくサードパーティ製の Python ラッパーを使っている可能性があります。lightweight-charts v5 の JavaScript に関する基本的なアドバイスを提示する前に、その点を明確に伝えてください。

基本モデル

依存関係の順に並べた 8 つのレイヤーです。多くの不具合は、これらを混同することで発生します。

  1. チャート — createChart(container, options) は IChartApi を返します。1 つのコンテナー要素につきチャートは 1 つです。
  2. シリーズ — chart.addSeries(SeriesType, options, paneIndex?) で追加します。各呼び出しは ISeriesApi を返します。v5 ではシリーズ型を明示的にインポートする必要があります。
  3. スケール — chart.timeScale()(ITimeScaleApi)、chart.priceScale(id)(IPriceScaleApi)。範囲、目盛り、自動スケーリング、表示を制御します。
  4. データモデル — { time, … } ポイントの配列です。Time = UTCTimestamp | BusinessDay | string です。UTCTimestamp はミリ秒ではなく秒です。各シリーズの時刻は一意で、昇順でなければなりません。
  5. インタラクション — chart.subscribeCrosshairMove、chart.subscribeClick、timeScale.subscribeVisibleLogicalRangeChange など。
  6. レイアウト — chart.panes()、chart.addPane()。範囲外の paneIndex を指定してシリーズを追加すると、ペインが自動的に作成されます。
  7. 拡張 — ペインプリミティブ、シリーズプリミティブ、カスタムシリーズ、ウォーターマーク、カスタムレンダラー(fancy-canvas を介した Canvas)。
  8. ラッパー — React/Vue/Web Components/iOS/Android。ライフサイクルはラッパーの責任であり、コアライブラリはフレームワークに依存しません。

v5 の基本事項

古いスニペットをコピーする際に注意すべき規約です。

import { createChart, CandlestickSeries, LineSeries } from 'lightweight-charts';

const chart = createChart(container, { /* ChartOptions */ });
const candles = chart.addSeries(CandlestickSeries, { /* options */ });
candles.setData([
    { time: 1700000000, open: 1, high: 2, low: 0.5, close: 1.5 },
]);

古いスニペットと比べた主な v5 の変更点:

  • chart.addSeries(SeriesType, options, paneIndex?) は、addLineSeries/addCandlestickSeries/… に代わるものです。
  • createSeriesMarkers(series, markers) は series.setMarkers(...) に代わるものです。返されるプリミティブが .setMarkers(...)/.markers() を所有します。
  • createTextWatermark(pane, options) と createImageWatermark(pane, imageUrl, options) は、watermark チャートオプションに代わるものです。
  • シリーズ型はツリーシェイクされます。ESM ではインポートが必要です。

スニペットに addLineSeries または series.setMarkers がある場合、v4 以前のものです。それを提示する前に、ユーザーのバージョンを確認してください。

タスクが v5 を対象としている場合は、v5 の API をそのまま示してください。v4 の構文を混在させて、曖昧にしないでください。

トリアージ(問題 → API → 避けるもの)

ユーザーからの質問まず確認すること回答に使うもの避けるもの
v5 シリーズの作成パッケージのバージョンと型定義chart.addSeries(SeriesType, options)addLineSeries / addCandlestickSeries
マーカーcreateSeriesMarkers のエクスポートマーカープリミティブ + 必須の colorseries.setMarkers
タイムゾーンフォーマッターの要件とデータのセマンティクスフォーマッターでの Intl.DateTimeFormat偽の timeScale.timezone
リアルタイム更新最後のバーのみか、全体の置き換えかseries.update(point)ティックごとの setData
ペインpaneIndex + chart.panes()v5 のペイン API、pane.setHeight非公開のウィジェット / DOM のハック
バーごとの色データポイントの色フィールドポイントの color/borderColor/wickColor色変更のための追加シリーズ / マーカー
プラグインプリミティブかカスタムシリーズかスケルトン / サンプル + 公開座標 API独自に作ったレンダラー名
v4 → v5 置き換えマトリックス

古くなったコピー&ペーストのスニペットが、最もよくある問題の原因です。次のように直接置き換えます。

古い、または誤った記述v5 での置き換え
chart.addLineSeries(options)chart.addSeries(LineSeries, options)
chart.addCandlestickSeries(options)chart.addSeries(CandlestickSeries, options)
series.setMarkers(markers)createSeriesMarkers(series, markers)
chart の watermark オプションcreateTextWatermark(chart.panes()[0], options)
createImageWatermark(pane, options)createImageWatermark(pane, imageUrl, options)
IPanePrimitivePaneRendererIPrimitivePaneRenderer
timeScale: { timezone }Intl.DateTimeFormat を使ったラベルフォーマッター
time: Date.now()(ミリ秒)UTCTimestamp 用の time: Math.floor(Date.now() / 1000)

ルーティングマップ(問題 → 参照先)

まずローカルの型定義を確認してください。以下のリポジトリパスは、上流の lightweight-charts チェックアウトにのみ存在します。利用側のアプリでは、インストール済みパッケージの型定義または公式ドキュメントを参照してください。

タスク標準的な参照先
最初のチャート/シリーズwebsite/docs/intro.mdx、website/tutorials/customization/
時間/範囲の動作website/docs/time-scale.md、website/docs/time-zones.md
リアルタイム/履歴website/tutorials/demos/realtime-updates.{mdx,js}、website/tutorials/demos/infinite-history.{mdx,js}
空白/ギャップwebsite/tutorials/demos/whitespace.{mdx,js}
価格フォーマット/ロケールwebsite/tutorials/customization/price-format.mdx、website/tutorials/demos/custom-locale.{mdx,js}
2 つのスケール/反転website/tutorials/how_to/two-price-scales.{mdx,js}、website/tutorials/how_to/inverted-price-scale.{mdx,js}
ペイン/価格と出来高website/docs/panes.md、website/tutorials/how_to/panes.{mdx,js}、website/tutorials/how_to/price-and-volume.{mdx,js}
マーカー/ツールチップ/凡例website/tutorials/how_to/series-markers.{mdx,js}、website/tutorials/how_to/tooltips.mdx、website/tutorials/how_to/legends.mdx
クロスヘア(プログラムによる操作)website/tutorials/how_to/set-crosshair-position*.js
透かしwebsite/tutorials/how_to/watermark.mdx
プラグイン/カスタムシリーズ/プリミティブwebsite/docs/plugins/、plugin-examples/src/plugins/
座標変換/ヒットテストsubscribeClick、coordinateToPrice、timeScale().coordinateToLogical の dist/typings.d.ts
非時間軸の水平スケール/オプションチャートcreateOptionsChart、createChartEx、IHorzScaleBehavior の dist/typings.d.ts
ピクセル単位の正確なレンダリングwebsite/docs/plugins/pixel-perfect-rendering/
React/Vue/Web Componentswebsite/tutorials/react/、website/tutorials/vuejs/、website/tutorials/webcomponents/
SSR/スクリプト読み込み/バンドラーインストール済みパッケージの dist/ ファイル、パッケージの exports、クライアント専用コンポーネントに関するフレームワークのドキュメント
iOS/Android ラッパーwebsite/docs/ios.md、website/docs/android.md
バージョン移行website/docs/migrations/from-v2-to-v3.md、from-v3-to-v4.md、from-v4-to-v5.md

これらのリポジトリパスがユーザーのプロジェクトに存在しない場合、通常の使い方に関する質問に答えるためだけに、ソースツリーの作成やクローンを求めないでください。node_modules/lightweight-charts/dist/typings.d.ts と簡潔な v5 の例を使用してください。

つまずきやすい点(カテゴリではなくアサーション)

時刻
  • UTCTimestamp は秒単位です。 Math.floor(Date.now() / 1000) を使用し、Date.now() は使用しないでください。
  • 組み込みの timeScale.timezone オプションはありません。 表示のみのタイムゾーン変換には、軸ラベルに timeScale.tickMarkFormatter を、クロスヘア/ホバーラベルに localization.timeFormatter(または独自のツールチップフォーマッター)を使用してください。DST に安全な IANA タイムゾーンのフォーマットには、Intl.DateTimeFormat(..., { timeZone })、Luxon、または date-fns-tz を使用してください。
  • タイムスタンプを事前にシフトすると、チャートの意味が変わります。 選択したタイムゾーンに目盛りを合わせられますが、UTC の時間軸上でのバーの位置も変わります。ユーザーが意図的にデータのシフトを望んでいる場合を除き、フォーマッターによる表示を優先してください。
  • シリーズデータは time の昇順で厳密に並び、値が重複していてはいけません。 重複したデータは通知なしに置き換えられ、順序が正しくないポイントは破棄されるか、エラーになります。
  • シリーズごとに使用できる時刻形式は 1 種類です。 BusinessDay('YYYY-MM-DD' 文字列または { year, month, day })か UTCTimestamp を使用できますが、1 つのシリーズ内で混在させないでください。
  • 空白ポイントには time のみを指定します(value/open/… は指定しません)。間隔を空けたり、オーバーレイを整列させたりするために使用してください。値に null を設定しないでください。
  • setData はデータセットを置き換え、表示範囲をリセットすることがあります。update(point) は time > last の場合は追加し、time === last の場合は置き換えます。 update(point, true) は既存の過去のポイントを更新できますが、処理が遅く、欠落している過去のポイントは挿入しません。過去のデータを先頭に追加するには、新しい配列を作成して setData を再度呼び出してください。先頭に追加するメソッドはありません。チャートの表示位置が変わらないように、表示中の論理範囲を保存して復元してください。
  • timeScale.setVisibleLogicalRange は論理範囲(バーのインデックス)を指定するもので、時刻ベースではありません。 時刻の範囲を指定するには setVisibleRange を、リセットするには fitContent() を使用してください。
スケールとペイン
  • 価格スケールを 2 つ表示するには、シリーズに priceScaleId: 'right'/'left' を割り当て、左側のスケールを表示可能にする必要があります。 chart.applyOptions({ leftPriceScale: { visible: true }, rightPriceScale: { visible: true } }) または chart.priceScale('left').applyOptions({ visible: true }) を使用してください。
  • オーバーレイシリーズ(priceScaleId: '' または任意のカスタム ID)には、デフォルトで自動スケーリングされる非表示のスケールが割り当てられます。軸ラベルを表示する場合は、明示的に表示してください。
  • autoscaleInfoProvider はレイアウト処理のたびに実行されます。 処理を軽量にし、呼び出しごとのメモリ割り当ては避けてください。
  • addSeries(_, _, paneIndex) は、paneIndex が現在のペイン数と同じ場合にペインを作成します。 ペインの順序は作成順です。サイズは chart.panes()[i].setHeight(px) で制御します。
  • ペインが移動する可能性がある場合は、ペインへの参照を保持してください。 const mainPane = chart.panes()[0] は同じ IPaneApi を保持し、swapPanes の後や移動後の現在のインデックスは mainPane.paneIndex() で取得できます。
  • 公開されている時間軸イベントを使って、別々のチャートを同期してください。 subscribeVisibleLogicalRangeChange と setVisibleLogicalRange を使用し、_private__chartWidget、paneWidgets、DOM オフセットを使った回避策は避けてください。
  • 価格スケールの幅は読み取り可能ですが、直接設定することはできません。 隣接するコンテナを整列させるときは、series.priceScale().width() または chart.priceScale(id).width() を使って測定してください。
マーカーとインタラクション
  • v5 のマーカーはプリミティブです。 const m = createSeriesMarkers(series, [...]); m.setMarkers([...]) を使用してください。v5 の ISeriesApi に series.setMarkers はありません。
  • マーカーの time は、そのシリーズの既存のデータポイントの time と一致している必要があります。 一致しないマーカーは通知なしに破棄されます。
  • subscribeCrosshairMove は、データ範囲外では param.time === undefined の状態で呼び出されます。値を読み取る前に、必ず null チェックを行ってください。
  • param.seriesData.get(series) は、バー間または最初のバーより前では undefined を返します。
  • クリック/クロスヘアの座標は API で変換する必要があります。 series.coordinateToPrice(y)/series.priceToCoordinate(price) と chart.timeScale().coordinateToLogical(x)/logicalToCoordinate(logical)/timeToCoordinate(time) を使用してください。Canvas の DOM ジオメトリから価格や時刻を推測しないでください。
プラグインとカスタムレンダリング
  • スキャフォールドやサンプルからプラグインを始めてください。 プリミティブをゼロから作成する前に、npm create lwc-plugin@latest と plugin-examples/ の利用をおすすめします。
  • インタラクティブな描画ツールには2つの要素が必要です。 描画用のプリミティブ/カスタムシリーズと、公開 API で座標を変換するチャートのインタラクションハンドラー(subscribeClick、subscribeCrosshairMove、ドラッグ状態)です。
  • CanvasRenderingTarget2D は lightweight-charts ではなく、fancy-canvas からインポートします。
  • ピクセルに揃った線には target.useBitmapCoordinateSpace(scope => …) を使用し、CSS ピクセル単位のロジックには target.useMediaCoordinateSpace(scope => …) を使用します。これらを混在させると、HiDPI ディスプレイでぼやけたり、サブピクセルのジッターが発生したりします。
  • IPanePrimitive のビューはペイン全体に描画され、ISeriesPrimitive のビューはシリーズ内にクリップされます。 適切な基底クラスを選んでください。
  • レンダラーのインターフェースは IPanePrimitivePaneRenderer ではなく IPrimitivePaneRenderer です。 ビューは IPanePrimitivePaneView で、その renderer() は IPrimitivePaneRenderer | null を返します。名前が非対称なのは意図的です。IPanePrimitivePaneRenderer のエクスポートはありません。不明な場合は dist/typings.d.ts を grep してください。
  • ICustomSeriesPaneView はプリミティブよりも重い仕組みです。 真のシリーズ API(データ、スケール、自動スケール)が必要な場合にのみ使用してください。装飾にはプリミティブを使用してください。
ラッパー(React/Vue など)
  • チャートは useEffect/onMounted で一度だけ作成し、クリーンアップ時に chart.remove() で破棄します。 レンダリングのたびに再作成すると、DOM が重複し、リスナーがリークします。
  • v5 では ResizeObserver が利用できる場合、autoSize: true で自動リサイズできます。 手動で制御する必要がある場合は、コンテナーに ResizeObserver を登録し、chart.resize(width, height)(または applyOptions({ width, height }))を呼び出します。
  • レンダリングのたびに props から setData を呼び出さないでください。 増分変更には series.update(...) を使用し、データセットを完全に置き換える場合にのみ setData を呼び出します。
  • applyOptions の undefined は「未指定」を意味し、「リセット」ではありません。 { priceFormatter: custom ? fmt : undefined } とすると、現在のフォーマッターがそのまま維持されます。localization のフォーマッターまたは autoscaleInfoProvider をクリアするには、null を渡します。その他のオプションにはリセット値がないため、デフォルト値を明示的に渡してください。
  • Next.js/SSR ではクライアント側でのみ使用してください。 チャートのコードを 'use client' コンポーネントに配置し、useEffect で作成します。必要に応じて、サーバーでレンダリングされるページから next/dynamic(..., { ssr: false }) でそのコンポーネントをインポートします。
  • プレーンな HTML では npm の名前解決は行われません。 スタンドアロンの .js ビルドは window.LightweightCharts を公開します。ブラウザーで ESM を使う場合は、実際の .mjs URL をインポートするか、インポートマップを使用してください。import { createChart } from 'lightweight-charts' が動作するのは、バンドラー/ランタイムがパッケージ名を解決する場合に限られます。

標準的なレシピ

リアルタイム更新
import { createChart, CandlestickSeries } from 'lightweight-charts';

const chart = createChart(container, {});
const series = chart.addSeries(CandlestickSeries, {});
series.setData(initialBars); // full history once

ws.onmessage = ev => {
    const bar = JSON.parse(ev.data); // { time, open, high, low, close }
    series.update(bar); // appends if time > last; replaces if time === last
};

update() が処理するのは最新のバーのみです。途中への挿入や先頭への追加には、配列を再構築して setData を呼び出します。

2つの価格スケール(左+右)
const right = chart.addSeries(LineSeries, { priceScaleId: 'right' });
const left  = chart.addSeries(LineSeries, { priceScaleId: 'left' });
chart.applyOptions({
    leftPriceScale: { visible: true },
    rightPriceScale: { visible: true },
});
独立したペインに表示する出来高
const price  = chart.addSeries(CandlestickSeries, {}, 0);
const volume = chart.addSeries(
    HistogramSeries,
    { priceFormat: { type: 'volume' } },
    1,
);
chart.panes()[1].setHeight(120);
バー/ポイントごとの色

個々のバーに色を付けるには、別の API ではなく、データポイントに色を指定します。

// Candlesticks: per-point color / borderColor / wickColor override series defaults
candles.setData([
    { time: 1700000000, open: 1, high: 2, low: 0.5, close: 1.5,
      color: '#26a69a', borderColor: '#26a69a', wickColor: '#26a69a' },
    { time: 1700003600, open: 1.5, high: 1.8, low: 1.1, close: 1.2,
      color: '#ef5350', borderColor: '#ef5350', wickColor: '#ef5350' },
]);

// Histogram (e.g. up/down volume): per-point color
volume.setData([
    { time: 1700000000, value: 100, color: 'rgba(38,166,154,0.5)' },
    { time: 1700003600, value: 80, color: 'rgba(239,83,80,0.5)' },
]);

Line/Area のポイントにも、ポイントごとの color を指定できます。ポイントの色を省略すると、シリーズのオプションの色が使われます。バーの色を変更するためにシリーズを追加したり、マーカーを使ったりしないでください。

シリーズマーカー
import { createSeriesMarkers } from 'lightweight-charts';

const markers = createSeriesMarkers(candles, [
    { time: 1700000000, position: 'aboveBar', color: '#e53935', shape: 'arrowDown', text: 'Sell' },
]);

markers.setMarkers([
    { time: 1700003600, position: 'belowBar', color: '#43a047', shape: 'arrowUp', text: 'Buy' },
]);

すべてのマーカーで color が必須です(position、shape、time も同様です)。text、size、id、price は省略可能です。setData() のポイントにマーカーオブジェクトを含めないでください。v5 では series.setMarkers(...) を呼び出さないでください。

タイムゾーン表示
const zone = 'America/New_York';
const formatTime = (timestamp: number) =>
    new Intl.DateTimeFormat('en-US', {
        timeZone: zone,
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
        hour12: false,
    }).format(new Date(timestamp * 1000));

chart.applyOptions({
    timeScale: {
        timeVisible: true,
        secondsVisible: true,
        tickMarkFormatter: (time) =>
            typeof time === 'number' ? formatTime(time) : String(time),
    },
    localization: {
        timeFormatter: (time) =>
            typeof time === 'number' ? formatTime(time) : String(time),
    },
});

timeScale: { timezone: 'America/New_York' } を独自に指定しないでください。取引所のセッション境界を現地時間に基づいて生成する必要がある場合は、表示形式とは別に、元のタイムスタンプをずらすことによるトレードオフを説明してください。

テキストのウォーターマーク
import { createTextWatermark } from 'lightweight-charts';

createTextWatermark(chart.panes()[0], {
    horzAlign: 'center',
    vertAlign: 'center',
    lines: [{ text: 'DEMO', color: 'rgba(0, 0, 0, 0.25)', fontSize: 48 }],
});

旧式のチャートオプション watermark は、v5 の API ではありません。

空白のギャップ
line.setData([
    { time: '2024-01-01', value: 10 },
    { time: '2024-01-02' }, // whitespace point: time only
    { time: '2024-01-03', value: 12 },
]);

ギャップを作るために value: null、undefined、NaN を使わないでください。

別々のチャートまたはペインを同期する
let syncing = false;

priceChart.timeScale().subscribeVisibleLogicalRangeChange((range) => {
    if (!range || syncing) return;
    syncing = true;
    indicatorChart.timeScale().setVisibleLogicalRange(range);
    syncing = false;
});

indicatorChart.timeScale().subscribeVisibleLogicalRangeChange((range) => {
    if (!range || syncing) return;
    syncing = true;
    priceChart.timeScale().setVisibleLogicalRange(range);
    syncing = false;
});

1つのチャート内にある v5 ペインには、chart.addSeries(SeriesType, options, paneIndex) と chart.panes()[i].setHeight(px) を優先して使用してください。元のペインが移動する可能性がある場合は、IPaneApi の参照を保持し、インデックスが常に 0 だと仮定せずに pane.paneIndex() を呼び出してください。

座標変換
chart.subscribeClick((param) => {
    if (!param.point || param.time === undefined) return;

    const price = series.coordinateToPrice(param.point.y);
    const logical = chart.timeScale().coordinateToLogical(param.point.x);
    if (price === null || logical === null) return;

    // Store { time: param.time, price } or convert logical back later:
    const x = chart.timeScale().logicalToCoordinate(logical);
    const y = series.priceToCoordinate(price);
});

描画ツールや注釈には、公開されている変換 API を使用してください。DOM キャンバスの座標だけでは、チャートの価格や時刻はわかりません。

Next.js のクライアント専用コンポーネント
'use client';

import { createChart, LineSeries } from 'lightweight-charts';
import type { ISeriesApi, LineData, Time } from 'lightweight-charts';
import { useEffect, useRef } from 'react';

export function LwcChart({ data }: { data: LineData<Time>[] }) {
    const ref = useRef<HTMLDivElement | null>(null);
    const seriesRef = useRef<ISeriesApi<'Line'> | null>(null);

    useEffect(() => {
        if (!ref.current) return;
        const chart = createChart(ref.current, { autoSize: true });
        const series = chart.addSeries(LineSeries);
        seriesRef.current = series;
        return () => {
            seriesRef.current = null;
            chart.remove();
        };
    }, []);

    useEffect(() => {
        seriesRef.current?.setData(data);
    }, [data]);

    return <div ref={ref} style={{ width: '100%', height: 320 }} />;
}

サーバーでレンダリングされる Next.js ページから、次のようにコンポーネントをインポートします。

import dynamic from 'next/dynamic';

const LwcChart = dynamic(() => import('./LwcChart').then((m) => m.LwcChart), {
    ssr: false,
});
プレーン HTML での読み込み

バンドラーがない場合は、スタンドアロンの IIFE ビルドを使用します。

<div id="chart" style="width: 600px; height: 300px"></div>
<script src="https://unpkg.com/lightweight-charts/dist/lightweight-charts.standalone.production.js"></script>
<script>
  const chart = LightweightCharts.createChart(document.getElementById('chart'));
  const series = chart.addSeries(LightweightCharts.LineSeries);
</script>

環境に応じて読み込み方法を選択してください。

  • バンドラー(Vite/webpack/Next): ベアな import { createChart } from 'lightweight-charts' を使用します。パッケージの exports が適切な ESM/CJS ビルドを解決します。
  • ブラウザーの <script>(バンドラーなし): 上記のスタンドアロン IIFE ビルドによって LightweightCharts グローバルが公開されます。ベアスペシファイアの解決は行われません。
  • ブラウザーのネイティブ ESM(<script type="module">): 具体的な .mjs URL(スタンドアロンの .mjs など)からインポートするか、インポートマップを追加してください。ベアな 'lightweight-charts' スペシファイアは解決されません。
  • SSR フレームワーク: クライアント専用として読み込んでください(上記の Next.js のレシピを参照)。サーバーコンポーネントのモジュールトップレベルではインポートしないでください。
プラグインのスターター
npm create lwc-plugin@latest

生成されたプロジェクトと plugin-examples/ をベースとして使用してください。まず拡張機能の種類を決めます。

  • プリミティブ(IPanePrimitive / ISeriesPrimitive、attachPrimitive でアタッチ) — 描画、オーバーレイ、ラベル、バンド、注釈、ヒットテスト向けです。これがデフォルトです。実際の系列動作が必要でない限り、プリミティブを使用してください。
  • カスタム系列(ICustomSeriesPaneView) — 拡張機能に独自のデータ、自動スケール、または価格/時間スケールとの統合が必要な場合に限って使用します。より複雑になるため、装飾目的では使用しないでください。

ドラッグ可能な描画には、series.attachPrimitive(...) または pane.attachPrimitive(...) でプリミティブをアタッチし、subscribeClick / subscribeCrosshairMove と座標変換 API を使用して操作を管理します。レンダラー専用の CanvasRenderingTarget2D は fancy-canvas からインポートしてください。レンダラーインターフェースは IPrimitivePaneRenderer です(IPanePrimitivePaneRenderer ではありません)。

金融以外のデータ
import { createOptionsChart } from 'lightweight-charts';

const chart = createOptionsChart(container);

まず、水平軸が本当に時間軸ではないかどうかを判断してください。

  • 真のカスタム水平スケール(オプションチェーン、時間以外のキーによるセンサーのスイープ):数値 x 軸には createOptionsChart を、カスタムの IHorzScaleBehavior を使用する場合は createChartEx を使用してください(どちらもローカルの型定義で確認してください)。
  • 金融以外の y 軸の単位だけが必要(温度、負荷)で、通常の時間/カテゴリ軸を使う場合:通常の createChart の系列モデルを維持し、ラベルが対象の分野に合うように priceFormat / localization.priceFormatter を設定してください。
  • 実際には順序付けられているカテゴリ x 軸: カテゴリを昇順の BusinessDay 文字列にマッピングするほうが、カスタムスケールより簡単です。ただし、その場合の軸は真のカテゴリ軸ではなく、日付形式の軸になります。
カスタム価格フォーマッター
chart.applyOptions({
    localization: {
        priceFormatter: (p: number) => `$${p.toFixed(2)}`,
    },
});

系列ごとに書式を設定するには、系列オプションで priceFormat: { type: 'custom', formatter, minMove } を設定します。チャートレベルの priceFormatter はフォールバックです。

組み込みの書式設定に戻すには、null を渡します。chart.applyOptions({ localization: { priceFormatter: null } })。undefined を渡した場合、現在のフォーマッターはそのまま使用されます。

最小限のペインプリミティブ
import type {
    IPanePrimitive,
    IPanePrimitivePaneView,
    IPrimitivePaneRenderer,
    Time,
} from 'lightweight-charts';
import type { CanvasRenderingTarget2D } from 'fancy-canvas';

class Overlay implements IPanePrimitive<Time> {
    paneViews(): IPanePrimitivePaneView[] { return [new View()]; }
}
class View implements IPanePrimitivePaneView {
    renderer(): IPrimitivePaneRenderer { return new Renderer(); }
}
class Renderer implements IPrimitivePaneRenderer {
    draw(target: CanvasRenderingTarget2D): void {
        target.useMediaCoordinateSpace(({ context, mediaSize }) => {
            context.fillStyle = 'rgba(0,0,0,0.05)';
            context.fillRect(0, 0, mediaSize.width, mediaSize.height);
        });
    }
}

chart.panes()[0].attachPrimitive(new Overlay());

動作する例は plugin-examples/src/plugins/ にあります。ゼロから作成する前に、そこの構成を参考にしてください。

実例

「新しいデータが届くたびに、チャートが右端に張り付きます。」

  1. 関係するレイヤー: データモデル(4)と時間スケール(3)。
  2. 原因の候補: 毎回の更新で series.update(...) ではなく series.setData(...) を呼び出しています。setData は表示範囲をリセットします。
  3. 確認: 呼び出し経路が setData と update のどちらかを確認します。setData の場合は、表示中の論理範囲を呼び出し前に取得し、呼び出し後に復元しているか確認します。これは v4 時代の回避策です。
  4. 修正: 増分更新には series.update(bar) を使い、全履歴を置き換える場合に限って setData を使います。ユーザーが明示的に最新データへの追従を希望している場合にのみ、chart.timeScale().scrollToRealTime() を使います。
  5. 参考資料: website/tutorials/demos/realtime-updates.js、website/docs/time-scale.md。

コード生成ルール

  • デフォルトは v5 です。 ユーザーのインストール済みパッケージまたはプロンプトで古いバージョンが指定されていない限り、v5 API を前提にします。v4 を使っている場合は、構文を混在させずに v5 への移行ポイントを説明します。
  • 実在するオプション名を使います。 利用者向けアプリでは node_modules/lightweight-charts/dist/typings.d.ts を、上流リポジトリでは dist/typings.d.ts または src/api/options/ を grep します。チャート、シリーズ、スケールには名前が似たオプションが多数あるため、そのオプションがどの階層に属するか確認してください。
  • 最小限のスニペットにします。 コードブロックごとに機能は1つだけにします。マーカー、ウォーターマーク、カスタムペインプリミティブを1つのスニペットにまとめると、各 API の役割が分かりにくくなります。
  • ユーザーのフレームワークに合わせます。 React ユーザーには useEffect のライフサイクルが必要ですが、バニラ JavaScript のユーザーには不要です。
  • 作り上げないでください。 API 名がインストール済みの型定義または上流ソースに見つからない場合、その API は存在しません。

回答の要件

lightweight-charts に関する質問に答える際は、次のとおりにします。

  1. 関連する v5 API を示します。
  2. 巨大なデモではなく、最小限のスニペットを1つ示します。
  3. そのタスクで特に注意すべき落とし穴を挙げます。
  4. 確認したローカルソース(バージョン/型定義)を伝えるか、確認できなかったことを明記します。

コメント