Scroll Viewer usecase & questions

Hi, I want to do something “crazy.” I’m aiming to use a GUI ScrollViewer to pan an arcRotateCamera. The idea is to position the scrollbars at the center of the bottom and right pages. When you drag the right scrollbar to the bottom, the camera should pan downward, and so on.

Several questions arise in this situation:

  1. First and foremost, what are your thoughts? Can I achieve this using the ScrollViewer, or was it designed for a completely different use case?
  2. If the answer to the first question is yes, then how can I position the scrollbars from code in the desired location?
  3. What is the range of values for this ScrollViewer?
  4. Which observer can I use to implement the logic related to the camera?
  5. I created a playground using a GUI grid, and for positioning and appearance, it looks almost as expected. However, I’m unsure if or how I can programmatically set the length of the scrollbars.

I tired something here

And btw, if you have other suggestion, I’m happy to hear. Thanks

Let me add @carolhmj our GUI Wizard and @PolygonalSun our Camera GURU to the thread :slight_smile:

1 Like

First of all, you can totally achieve then with the ScrollViewer. All that you really need to do is to access the ScrollBars from the ScrollViewer object and add an observer (callback) to onValueChangedObservable. The value will be from 0 (left/top side) to 1 (right/bottom side). From there, you just need to add to the ArcRotateCamera’s inertialPanningX/Y variables and the camera should be able to do the rest. Here’s an example PR showing that: Scroll Viewer Example with Grid of Images | Babylon.js Playground (babylonjs.com)

I’m not too familiar with this but I’d imagine that you might have to tweak the ScrollViewer’s width, height, and centerX/Y for that.

3 and 4 should be answered in the answer to 1.

For the fifth, you might be able to find more info on that in the docs for the ScrollViewer: Scroll Viewer | Babylon.js Documentation (babylonjs.com) or in the API pages:

2 Likes

Hi,
I believe what you are looking for to track the value of the bar is:

sv.horizontalBar.value
sv.verticalBar.value

(As already said above) the value range is 0 to 1. Zero being top or far left, 1 being bottom or far right.
After draw of the scrollviewer you may use these values and pass them (of course with conversion to the values of the camera) to act on the cam values. As said, you can use the onValueChanged observable for that (on both sv or slider). You might want to add an idealSize to your ADT to keep consistency. As for your question, is this the best way, I’m not all too sure. Fact is the sv is drawn in the ADT or a container of the ADT, which will change in size and ratio. You would need to give it a try. Else you could probably twist two (one for horizontal and one for vertical) ‘slider’.

I hope this helps.

1 Like

Not sure what you mean here. Basically the scrollbars fit the size of the container. Whenever a container is higher (or larger) than can be viewed, the scrollbar is visible (although you can also make it always or never visible). Now if you mean the height (or width) of the ‘thumb’, this is something different and the answer is yes. In fact you can even replace it with either a round shape (a disc) or going fancy :wink: with an image. You can also achieve the same using a ‘slider’, an ‘image based slider’. As I said, you would need to give one or both a try to see what best fits.

Edit: And then while quickly checking on your PG, I’m not sure you will want to pilot an arcRotate in ortho mode camera with this set-up. Might be a bit tricky and useless if you don’t want to orbit a target with the camera (which is basically what the arcRotateCamera is made for).

Edit1: Forgot to mention that if you choose to go the ‘slider’ way, you get the advantage that you can set the min and max value of the slider. You can also add ‘steps’ to it giving you more latitude to i.e. block on a view on a given range. The value you want to retrieve from a slider is simply ‘slider.value’ (or slider.step if you use steps).

1 Like

Hi, everyone! Thank you all!

Somehow, @PolygonalSun & @mawa gave me a brilliant idea. I realized I can use a GUI slider directly for the vertical axis and another one for the horizontal axis. With sliders, I have the flexibility to set the position, value, dimensions, and everything else.

You boys & girls are awesome! :fire::fire::fire:

Here is the final result

3 Likes

Looks good to me :clap: and then, @PolygonalSun sorry for my interference. I didn’t actually open your PG before replying. Only later realized that 95% was already in it (and kindly provided from your expertise which I will likely never reach :wink:) making most of my comments useless :zipper_mouth_face: I should really start to learn read the content before replying :sweat_smile: :joy:

Sorry @mawa , I didn’t see your last message till now. But I saw that you have the same idea with sliders instead of scrollbars, so this was definetly helpfull. Thank you

Hey, I have one more question

If I change the thumbWidth , the slider becomes a little bit smaller, and I understand why—because it slides until the middle of the thumb. The question is, can I change the thumbWidth without affecting the slider width?
I’ve tried a few combinations, but nothing has worked so far.
Thanks.

I’m not sure I understand it correctly, but if you mean the size of the thumb is greater than the bar and you want it the same size?… Yes, there’s a default that sets the bar 5px offset from the thumb (not sure why, but I guess is by design). You can change that by changing the barOffset property (line 78 in PG below).

1 Like

Sorry, I may not have been too clear :sweat_smile:. I mentioned ‘width,’ but I was actually thinking about ‘length.’

For example, with the slider from the bottom, if I don’t change the thumbWidth , the length of the slider is 100%. However, with the slider from the right, if I alter the thumbWidth , even if the length in the code is set to 100%, visually it becomes smaller (see the white line). The green line is what I expect, even when the thumb width is different than the standard.

Right. Sorry for misunderstanding.
Point is the thumb on the bar is based on its center (for whatever size it is). You could use negativ padding on the bar but in case of percentage/dynamic this might not be ideal to handle.
What I usually do in this case is that I constrain my slider in a container (i.e. a rectangle).
I set the background/bar color on the rectangle and make the bar transparent.
Let me know if you need me to illustrate through a PG…

Edit: Something like that (sorry just a rush, but you get the idea, hopefully :grinning:)

1 Like

Awesome hack :heart_eyes:
It looks doable, I’ll try it. Thank you

Yeah, a hack. Fact is there’s also a thumb clamped property but for some reason it doesn’t seem to work with a greater width/height ratio for the thumb. Figured this in the gui editor (btw a great tool to experiment with the gui). Though may be I’m just doing something wrong? Might be an opportunity for me to ask our gui angel :innocent: ? cc @carolhmj

Hey there! Trying to understand the behavior of the thumb better, at first I assumed that thumb clamped would affect, well, the thumb itself, but that doesn’t seem the case, at least not with a rectangular thumb. Instead, it affects the width of the bar - if thumbClamped is true, it makes the bar larger to accomodate for the larger thumb. It’s hard to see the difference with default values, but by making the thumb larger, it’s better to see: Using GUI slider | Babylon.js Playground (babylonjs.com)

Things look different if you use a circle thumb, in that case, thumbClamped does make the thumb smaller, and it only affects the extremes of the slider itself: Using GUI slider | Babylon.js Playground (babylonjs.com)

It all does seem inconsistent, so I want to ping @PatrickRyan : how do you think the thumbClamped property should behave, with circular and non circular thumbs?

@carolhmj, here is what I am seeing with the slider control in the PG. There is an interaction happening that isn’t completely clear between thumbWidth, isThumbCircle, and height. If the thumb is not a circle, the height of the thumb is driven by height and the width is driven by thumbWidth. If the thumb is not clamped, you can get a thumb control that is larger than the slider bar (which is what I would expect):

If I turn on thumb clamped, the height of the thumb should clamp to the height of the slider which is height - (2 * barOffset), however it does not take into account the barOffset and clamps to height:

If I enable the thumb as a circle, everything changes. Thumb clamped will now limit the diameter of the circle to what fits within the slider based on height - (2 * barOffset). There are also two circles added to the ends to make the slider fit a circular thumb, but it appears that these added circles don’t respect the alpha value in the bar color.

If I turn off clamp thumb, the circles at the end of the bar disappear, which is probably fine, but I could see wanting the slider bar to be rounded even if the thumb is larger than the slider bar. This may need to be a flag. But the main issue here is the interaction between height and thumbWidth when the thumb is a circle.

You can see that the thumb is larger than the bar, but not quite as large as height. Changing the value for thumbWidth does nothing for the thumb size as you can see here when I double the value to 60 from 30 in the last screen shot:

But when the thumbWidth gets larger than the height of the slider, then the thumb increases in size. However, there is still something going on because with a height of 80px on the slider, I need a thumbWidth of 100px to get close to the height of the control. So there is some interaction between height and thumbWidth when the thumb is a circle that is not obvious.

I would say that the property thumbWidth needs to act based on if the thumb is circular or not. If it is not circular, it works simply as the width of the thumb and the height of the thumb is set by the height of the slider. If the thumb is circular, thumbWidth should set the diameter of the thumb regardless of the slider height.

Then isThumbClamped will act in this way. If not circular, the height of the thumb = height - (2 * barOffset) and the width of the thumb is set by thumbWidth. If circular, the diameter of the thumb is height - (2 * barOffset) and thumbWidth is ignored because the diameter is already set.

I am also seeing some strange behavior on the width of the bar when isThumbClamped is toggled. This is off:

And notice how the bar width changes when isThumbClamped is enabled with the same settings as above:

It seems like there are several bugs interacting here, but some of these may have drastic ripple effects on back compat. Maybe we need to circle with @RaananW and see if there should be a v2 slider control that addresses these concerns while retaining back compat with a deprecated v1 slider.

@Biscuit, I noticed that you are using an ortho camera, but are not handling engine ratio or width/height changes which results in your canvas getting artificially stretched. Here is an example using ortho camera that updates when the window resizes to always keep the render proportional. Anytime you use an ortho camera, you want to handle this use case even in terms of opening your scene on a different monitor ratios. You are only interested in lines 6-28 in this PG.

4 Likes

@Biscuit and @mawa, we are going to do a deep dive into the slider class and design a V2 control so we can retain back compat and still address some of the concerns above. The issue here is timing since we are coming up to back-to-back holidays in the U.S. and out-of-office time we won’t be able to dive into the control and look at a redesign until January. Until then, however, if you have any requests of features that our sliders don’t currently have, please drop them in this thread so we can keep them in mind while designing what V2 looks like. Thanks for your help in identifying the concerns and for any suggestions you may make!

1 Like

Thanks Team @carolhmj @PatrickRyan for your insight and committment to always improve the BJS GUI and support us, users. :hugs:
I’m happy to hear that continuously improving the GUI is also part of v7 roadmap and, well, you know how much I value and use it :smiling_face_with_three_hearts:… Therefor, I will sure gladly contribute any way I can.

Fact is I will also be OoO for the next two months. After 5 years, I’m returning to my winter/summer retreat in OZ. But I will follow from there and will likely have more time in January. I’ll try find some time to further experiment and gather input from users. I can also offer my help to test and debug new version components.

As for the slider and the relation between thumb and bar, instinctively, I would probably try to work the thumb as a ‘part’, similar to other controls. I didn’t dive into the source code but, from a user perspective and in the editor, it’s kind of worked like a part, but not just entirely. As I said, just a feeling at this point. Anyways, thanks again and rest assured I will continue to use, challenge and push for the BJS GUI :smile: :crown:

2 Likes

Hey,
Apologies for reviving this thread, but I have a related question. For instance, when clicking on the slider, but not at its center, it snaps until its center aligns with the click position. How can I prevent this behavior? Additionally, when clicking on the slider, I want it to continue from its current position without snapping. Thank you

@Biscuit, it sounds like you want the slider to increase or decrease value at a certain rate based on where the pointer sits on the control when the mouse is clicked. This means you will have to take over the behavior of the mouse when hovering the control. You will likely need a combination of pointer hover, pointer down, pointer up and pointer move observables to create the behavior you want. You can see from this playground that the “koordinates” control will display local X/Y coordinates when hovering. You will likely need to convert these coordinates to if you are to the left or right of the thumb based on value. Then you will need to increment/decrement value on pointer down based on position. Since the default click behavior will likely still happen, it will probably happen first and since the values will be changed to your decrement value on the same frame, you shouldn’t see any popping. We don’t have anything exposed to disable the click behavior at the moment. This is just off the top of my head without any experimentation, so please feel free to ping me with questions. Probably best to start a new thread on it, though.

1 Like