Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple panes support #50

Open
nothingalike opened this issue Jun 11, 2019 · 143 comments · Fixed by ntf/lightweight-charts#1 or #1557 · May be fixed by #824
Open

Multiple panes support #50

nothingalike opened this issue Jun 11, 2019 · 143 comments · Fixed by ntf/lightweight-charts#1 or #1557 · May be fixed by #824
Labels
enhancement Feature requests, and general improvements. need proposal Requires a detailed proposal before more further.
Milestone

Comments

@nothingalike
Copy link

Looking through the documentation i dont see anything along these lines. I want to have my main chart but then add some additional data in a separate chart window. I believe some apps call it an Indicator Window. I was curious if its possible with this library.

@nothingalike nothingalike changed the title Is it possible to add an area to the chart. Is it possible to add an additional area to the chart. Jun 11, 2019
@timocov
Copy link
Contributor

timocov commented Jun 11, 2019

Do you want to add additional series to the new pane or to existing one? Something like this https://jsfiddle.net/TradingView/srwoh679/?

@nothingalike
Copy link
Author

I'm looking more for a new pane. which i assume i can just create another chart option but im afraid that would separate the zooming and paning causing both panes to be out of sync

@nothingalike
Copy link
Author

that being said, if i do need to create a new chart, is it possible for me to sync the zooming/paning via events.
ex: get event from one chart and apply to the second

@timocov
Copy link
Contributor

timocov commented Jun 11, 2019

If you'll create the new pane, the main one will be synced with that pane by visible range (also different series will share time scale and every series will extend points on time scale).

If you'll create the new chart, then you need to synchronize them yourself, but the charts is independent.

I would say you need to decide what do you want to get 🙂 Also, you can provide screenshots/links to any other platform where you've seen that.

is it possible for me to sync the zooming/paning via events

You can use

/**
* Adds a subscription to visible range changes to receive notification about visible range of data changes
* @param handler - handler (function) to be called on changing visible data range
*/
subscribeVisibleTimeRangeChange(handler: TimeRangeChangeEventHandler): void;
to get updates of visible time range changes and
/**
* Sets visible range of data
* @param range - target visible range of data
*/
setVisibleRange(range: TimeRange): void;
to set visible time range to other chart. Unfortunately we don't have documentation for that methods and we'll add them soon.

@nothingalike
Copy link
Author

Ideally i would not like to sync them myself, but it seems that i can take the 'pane' approach and use the itime-scale. that is probably what im looking for.

But for the sake of clarity, here is an image that can help visualize what im asking for.
The top being the main pane and the bottom part being the 'indicator' window or pane

image

@timocov
Copy link
Contributor

timocov commented Jun 11, 2019

Ah, ok, you want to use several panes on the same chart. Currently we haven't API to create additional panes but we've planned to add it in the future. For now you can do something like that https://jsfiddle.net/q3u2khzt/.

@nothingalike
Copy link
Author

I see that the chart-model has a createPane method on it, could I just use this? or would i not be able to add a data series to the new pane if i created it this way?

@timocov
Copy link
Contributor

timocov commented Jun 11, 2019

could I just use this?

It's not public API and we cannot guarantee you anything in this case.

@nothingalike
Copy link
Author

ah i see, so when adding a series of data via the chart-api it adds this new series to pane[0]. if this particular feature isn't currently being worked on, could i throw a pull request your way in the next few days?

@timocov
Copy link
Contributor

timocov commented Jun 11, 2019

if this particular feature isn't currently being worked on, could i throw a pull request your way in the next few days?

Which one? Supporting multiple panes?

@nothingalike
Copy link
Author

yes, supporting mutiple panes

@timocov
Copy link
Contributor

timocov commented Jun 11, 2019

Unfortunately we've started discuss about the design of that feature some time ago and there is some edge cases which requires some detailed investigation. It's one of our "after release features" and we'll add it soon.

@timocov
Copy link
Contributor

timocov commented Jun 11, 2019

I believe that all issues which can be taken by community will be marked with "help wanted" label. But this is a big feature and we need to be very accurate with it, its API and so on.

Thank you for your understanding.

@nothingalike
Copy link
Author

oh ok, cool. sounds good. ill keep my eye out for that feature. really appreciate your time

@timocov timocov changed the title Is it possible to add an additional area to the chart. Multiple panes support Jun 11, 2019
@timocov timocov added the enhancement Feature requests, and general improvements. label Jun 11, 2019
@triorr
Copy link

triorr commented Jun 23, 2019

Hello,

In the meantime, waiting for a better feature implementation , I've got some nice result adding some lines to the source code following timocov hint about the subscribeVisibleTimeRangeChange function.

First i added this function

public getBarSpacing(): number {
	return this._timeScale().barSpacing();
}

here


and this line

getBarSpacing(): number;

here


and now we can do something like this in our javascript

chart.timeScale().subscribeVisibleTimeRangeChange( syncHandler)
function syncHandler(e) {
    var barSpacing1 = chart.timeScale().getBarSpacing();
    var scrollPosition1 = chart.timeScale().scrollPosition();
    chart2.timeScale().applyOptions({rightOffset: scrollPosition1,barSpacing: barSpacing1})
}

@yuyic
Copy link

yuyic commented Aug 7, 2019

@triorr
@timocov
Is there any way to get/set the width of price bar? because the width is dynamic, I want to keep the width of two panels consistent.

@timocov
Copy link
Contributor

timocov commented Aug 7, 2019

@michelpmcdonald
Copy link

michelpmcdonald commented Aug 13, 2019

..... Also, you can provide screenshots/links to any other platform where you've seen that.

Try this site for an example of a chart that supports multiple synced panes:
www.tradingview.com

@timocov timocov added the need proposal Requires a detailed proposal before more further. label Aug 16, 2019
@0x48415a484952
Copy link

Hello,

In the meantime, waiting for a better feature implementation , I've got some nice result adding some lines to the source code following timocov hint about the subscribeVisibleTimeRangeChange function.

First i added this function

public getbarSpacing(): number {
	return this._timeScale().barSpacing();
}

here

and this line

getbarSpacing(): number;

here

and now we can do something like this in our javascript

chart.subscribeVisibleTimeRangeChange( syncHandler)
function syncHandler(e) {
    var barSpacing1 = chart.timeScale().getbarSpacing();
    var scrollPosition1 = chart.timeScale().scrollPosition();
    chart2.timeScale().applyOptions({rightOffset: scrollPosition1,barSpacing: barSpacing1})
}

hello, what is the equivalent code for standalone version ?

@0x48415a484952
Copy link

this feature is really cool if implemented like we could add an RSI which the range is between 0 and 100 and above that we could have the price candlesticks i tried to create such thing but could not achieve it here are some screen shots that in the second one after plotting RSI on the same chart the price candles get very unclear tried to tweak the scaleMargin but could not achieve a good result also i tried to create this on another chart below this chart which is ok but when the user scrolls the two different charts get out of sync so i think we should be able to plot them on one chart, i tried to look into the source code to add this feature as Triorr mentiond in here #50 (comment) but couldn't find the equivalent of this code on the standalone version.
KBTUSD
Screenshot_2019-09-04 Septillion

@karunkrishna
Copy link

karunkrishna commented Jan 27, 2020

Unfortunately we've started discuss about the design of that feature some time ago and there is some edge cases which requires some detailed investigation. It's one of our "after release features" and we'll add it soon.

Is there any update on this feature
There are are only two ways to render indicators studies;

  1. Overlay that use the same values as price (currently achievable)
  2. Paneled that use secondary values (Rendered in secondary chart, while time series is linked between charts)

We are missing support for 2.

Is there any documentation/jfiddle examples on using subscribeVisibleTimeRangeChange, getbarSpacing() if the feature will not be available in the near future?

@AurelReb
Copy link

AurelReb commented Apr 2, 2020

Hi, any update?
I'm looking exactly for this feature. Multiple panes would be very useful!
I also had an idea to handle this: there is an API to get the crosshair coordinates. Is it possible to place the crosshair on custom coordinates when the mouse isn't on the chart?

This way, we could get the time range, and the crosshair coordinates in the main chart, and copy it on the second chart.

@timocov
Copy link
Contributor

timocov commented Apr 2, 2020

Multiple panes would be very useful!

I'm sure no one will argue with that though 🙂

Is it possible to place the crosshair on custom coordinates when the mouse isn't on the chart?

No, we don't have such API for that.

Instead, I'd suggest everyone who needs this, trying to make a proposal for this feature. We'll happy to implement it (almost everything what needed for this feature already is implemented inside the lightweight-charts), but it's hard to provide good, readable and easy understandable API. That's the issue right now. If you have any ideas for that - please write them out here.

@ghost
Copy link

ghost commented May 18, 2020

@triorr i added 2 charts like you said and they are synced timescale with events. In the top is candlestick and bottom is histogram and my question is how can i make candlesticks and histogram bars stay in the same position? as you can see there is big space between candlesticks but histogram is still same.

@timocov It would be great if you have an idea about that.

Screen Shot 2020-05-18 at 4 12 07 PM

@nadayoon
Copy link

Ive taken @ntf repository and his fiddle from here [1] and created a minimal react version: https://github.com/Rassibassi/multipane_tradingview

[1] https://jsfiddle.net/adrianntf/6qea5ytv/

thank you very much

@SubigyaPanta
Copy link

Ive taken @ntf repository and his fiddle from here [1] and created a minimal react version: https://github.com/Rassibassi/multipane_tradingview

[1] https://jsfiddle.net/adrianntf/6qea5ytv/

This was really helpful for those of us who don't know react and use just plain js with script tags.

@FairyWorld
Copy link

V4.0.0 support multiple panes or not?

@julio899
Copy link

Do you want to add additional series to the new pane or to existing one? Something like this https://jsfiddle.net/TradingView/srwoh679/?

I want to implements like this -> https://jsfiddle.net/adrianntf/6qea5ytv/ this feature when be integrated?

@Atila027
Copy link

I want this feature.
Is there anyone who know about that well?

@tiger2014
Copy link

Do you want to add additional series to the new pane or to existing one? Something like this https://jsfiddle.net/TradingView/srwoh679/?

I want to implements like this -> https://jsfiddle.net/adrianntf/6qea5ytv/ this feature when be integrated?

have you update the official code of 'lightweight-charts'?

@jbunning
Copy link

Hi guys,

You can do something like this, works reasonably well:

      chart1.timeScale().subscribeVisibleTimeRangeChange((visibleTimeRange) => {
          chart2.timeScale().setVisibleRange(visibleTimeRange);
      });
      chart2.timeScale().subscribeVisibleTimeRangeChange((visibleTimeRange) => {
          chart1.timeScale().setVisibleRange(visibleTimeRange);
      });

@mhlvn
Copy link

mhlvn commented May 25, 2023

Hi!
this is my solution

setTimeout(() => {

        chart1.timeScale().subscribeVisibleLogicalRangeChange(() => {
                chart2.timeScale().setVisibleLogicalRange(chart1.timeScale().getVisibleLogicalRange());
        });

        chart2.timeScale().subscribeVisibleLogicalRangeChange(() => {
                chart1.timeScale().setVisibleLogicalRange(chart2.timeScale().getVisibleLogicalRange());
        });

}, 1000);

@Obiwanbde
Copy link

I see that the last two code share are running well enough. I could not manage to show tooltips for chart2 yet but I think it would be possible. Thanks.

@NFSS10
Copy link

NFSS10 commented Jun 25, 2023

Hi guys,

You can do something like this, works reasonably well:

      chart1.timeScale().subscribeVisibleTimeRangeChange((visibleTimeRange) => {
          chart2.timeScale().setVisibleRange(visibleTimeRange);
      });
      chart2.timeScale().subscribeVisibleTimeRangeChange((visibleTimeRange) => {
          chart1.timeScale().setVisibleRange(visibleTimeRange);
      });

This works pretty well but when zoomed in the charts weren't being synced as seamlessly as I wished. Using VisibleLogicalRange instead of VisiblelRange fixed that for me!

Here is the code If someone needs it:

chart1.timeScale().subscribeVisibleLogicalRangeChange(range => {
    chart2.timeScale().setVisibleLogicalRange(range);
});
chart2.timeScale().subscribeVisibleLogicalRangeChange(range => {
    chart1.timeScale().setVisibleLogicalRange(range);
});

@Marbemoreno
Copy link

I have 2 or more chart and I did this to sync both


chart.timeScale().subscribeVisibleLogicalRangeChange((range) => {
              if (indicatorAux.chart) {
                indicatorAux.chart.timeScale().setVisibleLogicalRange(range);
              }
            });
            // Stop move in not current charts (this is because Ineed this behavior)
            indicatorAux.chart
              .timeScale()
              .subscribeVisibleLogicalRangeChange((range) => {
                if (indicatorAux.chart.timeScale())
                  indicatorAux.chart
                    .timeScale()
                    .setVisibleLogicalRange(
                      chart.timeScale().getVisibleLogicalRange()
                    );
              });
          });

But I still want to show the crosshair line in both (chart) at the same time how could I do that?

@bonald
Copy link

bonald commented Oct 19, 2023

//sync crosshair
// Define a function to handle crosshair movement synchronization
const syncCrosshairMovement = (sourceChartRef, targetChartRefs) => {
return sourceChartRef.current.subscribeCrosshairMove((param) => {
if (param.point !== undefined && param.time !== undefined) {
const dataPoint = getCrosshairDataPoint(sourceChartRef.current, param);
targetChartRefs.forEach((chartRef) => {
syncCrosshair(chartRef.current, obvSeriesRef.current, dataPoint);
syncCrosshair(chartRef.current, openInterestSeriesRef.current, dataPoint);
syncCrosshair(chartRef.current, candleSeriesRef.current, dataPoint);
});
}
});
};

// Define a function to handle visible logical range synchronization
const syncVisibleLogicalRange = (sourceChartRef, targetChartRefs) => {
return sourceChartRef.current.timeScale().subscribeVisibleLogicalRangeChange((timeRange) => {
if (timeRange && typeof timeRange === "object" && timeRange.hasOwnProperty("from") && timeRange.hasOwnProperty("to")) {
targetChartRefs.forEach((chartRef) => {
chartRef.current.timeScale().setVisibleLogicalRange(timeRange);
});
} else {
targetChartRefs.forEach((chartRef) => {
chartRef.current.timeScale().resetTimeScale();
});
}
});
};

const targetChartRefs1 = [chartRef2, chartRef3];
const targetChartRefs2 = [chartRef, chartRef3];
const targetChartRefs3 = [chartRef, chartRef2];

  // Call the sync functions for each source chart
  syncCrosshairMovement(chartRef, targetChartRefs1);
  syncVisibleLogicalRange(chartRef, targetChartRefs1);

  syncCrosshairMovement(chartRef2, targetChartRefs2);
  syncVisibleLogicalRange(chartRef2, targetChartRefs2);

  syncCrosshairMovement(chartRef3, targetChartRefs3);
  syncVisibleLogicalRange(chartRef3, targetChartRefs3);

@DeVoresyah
Copy link

the multipane feature is really helpful, and I wonder if multipane can do something like this. instead of showing 2 charts, how about merging them into an existing chart and then adding 1 more yAxis on the right?
image

@dc-thanh
Copy link

Even though the two charts are synchronized, there seems to be an issue with the crosshair. Chart 1 has more data points than Chart 2, but the data points on both charts are similar in terms of timing.

Screen.Recording.2023-12-14.at.10.32.03.AM.mp4

@NFSS10
Copy link

NFSS10 commented Dec 14, 2023

Even though the two charts are synchronized, there seems to be an issue with the crosshair. Chart 1 has more data points than Chart 2, but the data points on both charts are similar in terms of timing.
Screen.Recording.2023-12-14.at.10.32.03.AM.mp4

This is the correct behavior, if you want the crosshair to be horizontally aligned everytime, you need to expand the lower chart so that both charts fill the same space.

I think you could use setVisibleLogicalRange() or setVisibleRange() to force that behaviour

@thichmautim
Copy link

The versions mentioned above use LW 3.6, which's missing some important features like addBaselineSeries. For those willing to build the most recent (4.0-dev) LW charts + ntf's multipane patch, either merge both repos, or use @john-wallace-dev recent fork:

git clone https://github.com/john-wallace-dev/lightweight-charts
cd lightweight-charts
yarn install --ignore-engines

The standalone lib will be built into dist folder.

Thank you too much!!!

@841660202
Copy link

the multipane feature is really helpful, and I wonder if multipane can do something like this. instead of showing 2 charts, how about merging them into an existing chart and then adding 1 more yAxis on the right? image

Same question, how to achieve it?

@julio899
Copy link

julio899 commented Feb 2, 2024

the multipane feature is really helpful, and I wonder if multipane can do something like this. instead of showing 2 charts, how about merging them into an existing chart and then adding 1 more yAxis on the right? image

Same question, how to achieve it?

2024-02-02_07-31-54.mp4

you need that, the data in the same data time and add event when scroll or zoom in the chart also use subscribeCrosshairMove, subscribeVisibleLogicalRangeChange & coordinateToPrice

@rwitzlib
Copy link

rwitzlib commented Feb 7, 2024

Here is an updated fork of @ntf / @john-wallace-dev forks that people can reference if they'd like: https://github.com/rwitzlib/lightweight-charts
Currently updated to v4.1.3 but Ill try to keep this updated until multi-pane is officially supported

@rwitzlib
Copy link

rwitzlib commented Feb 13, 2024

@rwitzlib Can you explain to me how can I add another pane to the chart with your fork ?

Here is an example of using this library. For these examples, assume chart is a reference to the chart object resulting from the createChart method. I dont use swapPane or getPaneElements so I cant attest to those unfortunately.

Adding a pane:
pane: can be set to an int (0, 1, 2, 3, etc.). If there are no studies with the pane number 1 or greater, a new pane will be created and the study will be added to that pane.

image

Removing a pane:
paneToRemove is an int

image

The Result:
image

@madnight
Copy link

madnight commented Mar 1, 2024

@rwitzlib

Can you provide a dist standalone production version e.g. on UNPKG or as Github Release Asset?

@cat3311
Copy link

cat3311 commented Mar 2, 2024

Can you provide a dist standalone production version e.g. on UNPKG or as Github Release Asset?

lightweight-charts.standalone.development.zip

@cat3311
Copy link

cat3311 commented Mar 2, 2024

@rwitzlib

image

Thanks for the improved charts with pane
Can you make a separate watermark for each panel?

@tiger2014
Copy link

Here is an updated fork of @ntf / @john-wallace-dev forks that people can reference if they'd like: https://github.com/rwitzlib/lightweight-charts Currently updated to v4.1.3 but Ill try to keep this updated until multi-pane is officially supported

Hi rwitzlib, I have a basicquestion: how to use your code in file with extention .html?

@illetid illetid mentioned this issue Apr 5, 2024
3 tasks
@gokuschoyi
Copy link

gokuschoyi commented Apr 6, 2024

Here is an updated fork of @ntf / @john-wallace-dev forks that people can reference if they'd like: https://github.com/rwitzlib/lightweight-charts Currently updated to v4.1.3 but Ill try to keep this updated until multi-pane is officially supported

Hey @rwitzlib, I tried to install the fork by adding it to my package.json as follows
"lightweight-charts": "github:rwitzlib/lightweight-charts"

and did npm install. I get the following error

Error: ERROR: Failed to set up chrome-headless-shell v121.0.6167.85! Set "PUPPETEER_SKIP_DOWNLOAD" env variable to skip download.

I have then set the PUPPETEER_SKIP_DOWNLOAD to true and I then get another error as follows :

Error: Cannot find module '/home/goku/test/node_modules/lightweight-charts/scripts/githooks/install.js'

I then set the PUPPETEER_SKIP_DOWNLOAD to false and tried

Correction, with --ignore-scripts all the scripts are ignored and it makes sense that the dist is not present after install.

npm install --ignore-scripts puppeteer

This installs the package but without the /dist folder in the node modules.

Performing the same operation with john-wallace-dev's fork works as expected
"lightweight-charts": "github:john-wallace-dev/lightweight-charts",

I wanted to know what could be going wrong here? Any help is appreciated.

@HassanAhari
Copy link

        chart.timeScale().subscribeVisibleLogicalRangeChange((timeRange: Range<number> | null) => {
          if (timeRange) {
            sub_chart?.timeScale().setVisibleLogicalRange(timeRange);
          }
        });

        sub_chart?.timeScale().subscribeVisibleLogicalRangeChange((timeRange: Range<number> | null) => {
          if (timeRange) {
            chart.timeScale().setVisibleLogicalRange(timeRange);
          }
        });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Feature requests, and general improvements. need proposal Requires a detailed proposal before more further.
Projects
None yet