Overview of Pane Primitives
autoscaleInfo because they are not tied to a price scale.website·Indexed 29 days ago
https://tradingview.github.io/lightweight-charts/A client-side library for drawing financial data on a canvas. Documentation covers version 5.2, including installation, series and chart types, price and time scales, and pane management. Includes comprehensive guides on plugin development for custom series and primitives, pixel-perfect canvas rendering, framework integrations like React, and migration paths from v2 through v5.
autoscaleInfo because they are not tied to a price scale.A series primitive follows a three-tier architecture to optimize rendering performance by separating state, coordinate calculation, and pixel drawing:
CanvasRenderingContext2D API to put pixels on the canvas (the actual drawing).During a redraw, the library first lets views recompute coordinates and then calls the renderers, avoiding unnecessary recomputations.
CanvasRenderingTarget2D object. This object allows you to execute drawing logic using the browser's 2D Canvas API. It provides two primary scopes for rendering: useMediaCoordinateSpace and useBitmapCoordinateSpace.createContext, forwardRef, and useImperativeHandle. This approach allows a parent <Chart /> component to manage the chart instance and provide it to child <Series /> components via context, while still exposing the chart API to the application via refs for manual updates (e.g., calling .update() on a series).import { createChart, LineSeries, AreaSeries } from 'lightweight-charts';
import React, {
createContext,
forwardRef,
useCallback,
useContext,
useEffect,
useImperativeHandle,
useLayoutEffect,
useRef,
useState,
} from 'react';
const Context = createContext();
export function Chart(props) {
const [container, setContainer] = useState(false);
const handleRef = useCallback(ref => setContainer(ref), []);
return (
<div ref={handleRef}>
{container && <ChartContainer {...props} container={container} />}
</div>
);
}
export const ChartContainer = forwardRef((props, ref) => {
const { children, container, layout, ...rest } = props;
const chartApiRef = useRef({
isRemoved: false,
api() {
if (!this._api) {
this._api = createChart(container, {
...rest,
layout,
width: container.clientWidth,
height: 300,
});
this._api.timeScale().fitContent();
}
return this._api;
},
free(series) {
if (this._api && series) {
this._api.removeSeries(series);
}
},
});
useLayoutEffect(() => {
const currentRef = chartApiRef.current;
const chart = currentRef.api();
const handleResize = () => {
chart.applyOptions({
...rest,
width: container.clientWidth,
});
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
chartApiRef.current.isRemoved = true;
chart.remove();
};
}, []);
useImperativeHandle(ref, () => chartApiRef.current.api(), []);
useEffect(() => {
const currentRef = chartApiRef.current;
currentRef.api().applyOptions({ layout });
}, [layout]);
return (
<Context.Provider value={chartApiRef.current}>
{props.children}
</Context.Provider>
);
});
export const Series = forwardRef((props, ref) => {
const parent = useContext(Context);
const context = useRef({
api() {
if (!this._api) {
const { data, type, ...rest } = props;
this._api =
type === 'line'
? parent.api().addSeries(LineSeries, rest)
: parent.api().addSeries(AreaSeries, rest);
this._api.setData(data);
}
return this._api;
},
free() {
if (this._api && !parent.isRemoved) {
parent.free(this._api);
}
},
});
useLayoutEffect(() => {
const currentRef = context.current;
currentRef.api();
return () => currentRef.free();
}, []);
useLayoutEffect(() => {
const currentRef = context.current;
const { data, ...rest } = props;
currentRef.api().applyOptions(rest);
});
useImperativeHandle(ref, () => context.current.api(), []);
return (
<Context.Provider value={context.current}>
{props.children}
</Context.Provider>
);
});To integrate Lightweight Charts™ into a complex React application, use a hierarchical component structure where a parent Chart component manages the chart instance and child Series components manage individual data series.
Because React hooks (like useEffect) execute in a bottom-up order during instantiation, a child Series component might attempt to initialize before the parent Chart has created the chart instance. To prevent this, use useRef, useImperativeHandle, and React.createContext to share internal references and lifecycle methods from the parent chart to its children.
<ChartComponent>
<ChartContainer>
<SeriesComponent 1>
<ChildComponent />
</SeriesComponent 1>
<SeriesComponent N>
<ChildComponent />
</SeriesComponent N>
</ChartContainer>
</ChartComponent>// v4 -> v5
ISeriesPrimitivePaneView -> IPrimitivePaneView
ISeriesPrimitivePaneRenderer -> IPrimitivePaneRenderer
SeriesPrimitivePaneViewZOrder -> PrimitivePaneViewZOrderTradingView offers several products depending on the level of integration and functionality required. Note that none of these products provide market data (except for Widgets); you must provide your own data source for Lightweight Charts™, Advanced Charts, and Trading Platform.
<figure> instead of a generic <div> when providing the container for the createChart method.<figure id="chart"></figure>