Skip to content

Commit

Permalink
Merge pull request #1613 from tradingview/horizontal-price-scale-example
Browse files Browse the repository at this point in the history
add how to example for horizontal price scale
  • Loading branch information
SlicedSilver committed Jun 14, 2024
2 parents 86aa897 + 4c1e8c8 commit f9cbe08
Show file tree
Hide file tree
Showing 6 changed files with 503 additions and 5 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ module.exports = {
'@typescript-eslint/no-misused-promises': 'off',
'@typescript-eslint/no-unnecessary-qualifier': 'off',
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
'@typescript-eslint/no-unsafe-argument': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
Expand Down
4 changes: 3 additions & 1 deletion website/plugins/enhanced-codeblock/theme/CodeBlock/chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ interface ChartProps {

type IFrameWindow<TVersion extends keyof LightweightChartsApiTypeMap> = Window & {
createChart: LightweightChartsApiTypeMap[TVersion]['createChart'];
createChartEx: TVersion extends '4.1' | 'current' ? LightweightChartsApiTypeMap[TVersion]['createChartEx'] : undefined;
run?: () => void;
};

Expand Down Expand Up @@ -57,10 +58,11 @@ export function Chart<TVersion extends keyof LightweightChartsApiTypeMap>(props:

const injectCreateChartAndRun = async () => {
try {
const { module, createChart } = await importLightweightChartsVersion[version](iframeWindow);
const { module, createChart, createChartEx } = await importLightweightChartsVersion[version](iframeWindow);

Object.assign(iframeWindow, module); // Make ColorType, etc. available in the iframe
iframeWindow.createChart = createChart;
iframeWindow.createChartEx = createChartEx;
iframeWindow.run?.();
} catch (err: unknown) {
// eslint-disable-next-line no-console
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export type LightweightChartsVersion = Version | 'current';
export interface LightweightChartsApiGetterResult<T extends keyof LightweightChartsApiTypeMap> {
module: LightweightChartsApiTypeMap[T];
createChart: LightweightChartsApiTypeMap[T]['createChart'];
createChartEx: T extends '4.1' | 'current' ? LightweightChartsApiTypeMap[T]['createChartEx'] : undefined;
}

export type LightweightChartsApiGetters = {
Expand All @@ -50,7 +51,7 @@ export const importLightweightChartsVersion: LightweightChartsApiGetters = {
return result;
};

return { module, createChart };
return { module, createChart, createChartEx: undefined };
},
'4.0': async (window: Window) => {
const module = await import('lightweight-charts-4.0');
Expand All @@ -61,7 +62,7 @@ export const importLightweightChartsVersion: LightweightChartsApiGetters = {
return result;
};

return { module, createChart };
return { module, createChart, createChartEx: undefined };
},
4.1: async (window: Window) => {
const module = await import('lightweight-charts-4.1');
Expand All @@ -72,7 +73,13 @@ export const importLightweightChartsVersion: LightweightChartsApiGetters = {
return result;
};

return { module, createChart };
const createChartEx = (container: string | HTMLElement, behaviour: Parameters<typeof module.createChartEx>[1], options?: Parameters<typeof module.createChartEx>[2]) => {
const result = module.createChartEx(container, behaviour, options);
addResizeHandler(window, container as HTMLElement, result.resize.bind(result));
return result;
};

return { module, createChart, createChartEx: createChartEx as typeof module.createChartEx };
},
current: async () => {
const module = await import('../../../../..');
Expand All @@ -83,6 +90,12 @@ export const importLightweightChartsVersion: LightweightChartsApiGetters = {
return result;
};

return { module, createChart };
const createChartEx = (container: string | HTMLElement, behaviour: Parameters<typeof module.createChartEx>[1], options?: Parameters<typeof module.createChartEx>[2]) => {
const result = module.createChartEx(container, behaviour, options);
addResizeHandler(window, container as HTMLElement, result.resize.bind(result));
return result;
};

return { module, createChart, createChartEx: createChartEx as typeof module.createChartEx };
},
};
1 change: 1 addition & 0 deletions website/tutorials/how_to/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ module.exports = {
globals: {
document: false,
createChart: false,
createChartEx: false,
},
};
131 changes: 131 additions & 0 deletions website/tutorials/how_to/horizontal-price-scale.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// remove-start
// Lightweight Charts™ Example: Horizontal Price Scale
// https://tradingview.github.io/lightweight-charts/tutorials/how_to/horizontal-price-scale

// remove-end
function markWithGreaterWeight(a, b) {
return a.weight > b.weight ? a : b;
}

// remove-line
/** @type {import('lightweight-charts').IHorzScaleBehavior} */
class HorzScaleBehaviorPrice {
constructor() {
this._options = {};
}

options() {
return this._options;
}

setOptions(options) {
this._options = options;
}

preprocessData(data) {}

updateFormatter(options) {
if (!this._options) {
return;
}
this._options.localization = options;
}

createConverterToInternalObj(data) {
return price => price;
}

key(internalItem) {
return internalItem;
}

cacheKey(internalItem) {
return internalItem;
}

convertHorzItemToInternal(item) {
return item;
}

formatHorzItem(item) {
return item.toFixed(this._precision());
}

formatTickmark(item, localizationOptions) {
return item.time.toFixed(this._precision());
}

maxTickMarkWeight(marks) {
return marks.reduce(markWithGreaterWeight, marks[0]).weight;
}

fillWeightsForPoints(sortedTimePoints, startIndex) {
const priceWeight = price => {
if (price === Math.ceil(price / 100) * 100) {
return 8;
}
if (price === Math.ceil(price / 50) * 50) {
return 7;
}
if (price === Math.ceil(price / 25) * 25) {
return 6;
}
if (price === Math.ceil(price / 10) * 10) {
return 5;
}
if (price === Math.ceil(price / 5) * 5) {
return 4;
}
if (price === Math.ceil(price)) {
return 3;
}
if (price * 2 === Math.ceil(price * 2)) {
return 1;
}
return 0;
};
for (let index = startIndex; index < sortedTimePoints.length; ++index) {
sortedTimePoints[index].timeWeight = priceWeight(
sortedTimePoints[index].time
);
}
}

_precision() {
return this._options.localization.precision;
}
}

const horzItemBehavior = new HorzScaleBehaviorPrice();

const chartOptions = {
layout: {
textColor: CHART_TEXT_COLOR,
background: { type: 'solid', color: CHART_BACKGROUND_COLOR },
},
localization: {
precision: 2, // custom option
},
};

// remove-line
/** @type {import('lightweight-charts').IChartApi} */
const chart = createChartEx(
document.getElementById('container'),
horzItemBehavior,
chartOptions
);

const lineSeries = chart.addLineSeries({ color: LINE_LINE_COLOR });

const data = [];
for (let i = 0; i < 5000; i++) {
data.push({
time: i * 0.25,
value: Math.sin(i / 100) + i / 500,
});
}

lineSeries.setData(data);

chart.timeScale().fitContent();
Loading

0 comments on commit f9cbe08

Please sign in to comment.