project-nv / night-vision

Highly customizable charting library, created for professional traders
https://nightvision.dev
MIT License
252 stars 58 forks source link

Editable/interactive box example ? #25

Closed Jonarod closed 1 year ago

Jonarod commented 1 year ago

Description

I have been using TVJS for around 6 months now, and found this rewrite recently which is clearly cleaner and faster. I would like to port my app into this new version but it is lacking of toolbox unfortunately.

I see on the roadmap that toolbox and tools in general are quite not the priority at the moment, and it is ok, however I wanted to ask if you could hint us on how to get started with drawing a simple box interactively (4 edges + 4 middle edges, like in TradingView, that one can edit directly from the chart). I have no clue if what I am asking is too much work to do for now to be honest, but if we could have a starting point to draw this kind of editable box, I think one could infer a lot of tools from this one only: Fibonacci, Risk:Reward boxes, measurements, and any trend lines / rays could be easily derived from the code of a box.

Suggested solution

Provide starting point code/api to draw an interactive box on chart. This would allow us to create our own toolbox while the official/native toolbox of the project is done.

Alternative

No response

Additional context

No response

Validations

C451 commented 1 year ago

Hey, the plan now is to move towards the next-gen stuff and implement the old features more slowly. Tools are one of the last things, bc users of TVJS project are mostly algo/indicator traders. For general charting I personally still use tv.com & really like the experience.

There's an option to port tools from TVJS here, they are built based on events & datacube (which is written in valinalla js).

Jonarod commented 1 year ago

Sorry I feel like maybe I did not express myself correctly or I've let my issue with a scope too large. Let me reframe it please.

Specifically, where should I inject any draw() function at runtime? I guess I could create some NavyJS script on the fly and update my NightVision Chart object, but is there a better way in VanillaJS?

Finally, provided I can inject a drawing on the chart, how can I get a hold of this very new object on hover/click ? Should I monitor the cursor coordinates and try to see if those roughly match my previous drawing, then if the cursor is close enough I update the objects' script to make it "pop" then move it ? Or is there any higher level feature/API I could use for this?

Thank you again !

C451 commented 1 year ago

Ah ok. You don't need to add .navy on the fly. Overlays are shaders/programs that display your data on the screen. What you need is to create an overlay that listens to mouse events & updates the data, when added to the chart it can emit special events to modify the overlay props, such as pin positions (see tvjs DataCube). Recently I added support of mouse events, but the lib doesn't handle tool events automatically yet. E.g.:

https://github.com/tvjsx/trading-vue-js/blob/master/src/components/overlays/LineTool.vue#L54

The only way right now is to dig into the source of tvjs and replicate this stuff.

Jonarod commented 1 year ago

In TVJS, one could easily add overlays like this:

 <TradingVue ref="tvchart" 
    :data="chart"
    :overlays="[MyCustomOverlayFunction]"
></TradingVue>

MyCustomOverlayFunction could indeed be the LineTool you mentioned and I could eventually code some fancy draw() function which brings ctx to interact back and forth with the actual chart.

Now in night-vision, where should I inject MyCustomOverlayFunction if not on scripts as .navy scripts ? Sorry I can't really see another way right now. In fact, my understanding is that the overlays array in chart options does not quite fill the same function as TVJS's overlays used to (it only accepts a few parameters but will not accept any Class or draw function.

So I guess I can re-write the ex LineTool logic to fit my needs, that is a good starting point, and using chart.events.on() and mouse events I could manage to communicate back and forth with any components, but how do I make the draw() function executed and inherit actual ctx of the current chart without .navy scripts ?

EDIT: Ultimately, I see I could force use of vanilla JS by injecting a new object into chart.scriptHub.prefabs which would export a make() function itself exposing the draw(), legend() functions etc... or I could just create a custom .navy file like I mentioned. Either way, that is not my issue. However, I cannot find a way to TRIGGER the relevant script on-demand without referencing the custom overlay into chart.panes.overlays with actual data. In the case of DRAWING to the chart interactively, data are not static and do not have the time, value1, value2, value3... structure. In fact for instance, in the case of box, one needs to draw the ctx.fillrect(x, y, w, h) with 2 points on the same timestamp reference.

Now, I could easily do :

ctx = document.getElementById('nvjs-canvas-0-0').getContext("2d");
ctx.fillRect(10, 20, 200, 400);

and this would definitely draw the desired box. However, it obviously disappears as soon as the chart moves due to repainting of the chart. So, if there is no way to inject custom scripts easily for now, how could I register my box into the chart core internals so that it "remembers" it even after updates ?

C451 commented 1 year ago

I mean I have nothing to add over what already said. Yes, .navy files is a replacement for vue Overlays. Almost the same methods. Pin positions should be stored in props instead of settings.

It's better to wait for the official implementation.

Jonarod commented 1 year ago

No problem, thanks anyways. Will try using the .navy hack + layout helpers for now, and wait for the official implementation.