Closed dtturcotte closed 4 months ago
Add method scrollToChild
to align top/left of child to top/left of panel. See this demo, line 41.
I was hoping for it to only scroll down to the element to reveal it, but not past it. So, for example, if scrolling to item-20 (panel.scrollToChild(panel.getByName('item-20', true));)
, it would look like this:
Add align
parameter to scrollToChild
method. Now item-20
will be scrolled at bottom of panel in this demo.
Thank you. Please let me know when you're able to update the npm
package. Hopefully soon?
NPM package will be upgraded at end of this month.
Re-opening this. I'm trying to use scroll to child, but with a Phaser.GameObjects.Container
. The scrollToChild
works with anything that's not a container, but I need it to work with a container. I've set the size of my containers to the total size of their contents, but I still get this error.
ScrollToChild.js:60 Uncaught (in promise) TypeError: child.getTopLeft is not a function at RexUIScrollablePanel.AlignChild (ScrollToChild.js:60:56) at RexUIScrollablePanel.ScrollToChild [as scrollToChild] (ScrollToChild.js:9:24) at RexUIScrollablePanel.update (rexUIScrollablePanel.ts:151:1) at QuestStatusUI.addMissionJourney (questStatusUI.ts:229:1) at new QuestStatusUI (questStatusUI.ts:22:1) at WatchComponent.addSubUi (watchComponent.ts:91:1) at WatchComponent.addUi (watchComponent.ts:122:1) at new WatchComponent (watchComponent.ts:21:1) at GUIScene.addComponents (guiScene.ts:709:1) at GUIScene.addUi (guiScene.ts:719:1)
Referencing the source code, it's happening here
default:
var dTop = scrollableBlock.top - child.getTopLeft().y; <---------- ERROR HERE
var dBottom = scrollableBlock.bottom - child.getBottomLeft().y;
if ((dTop <= 0) && (dBottom >= 0)) {
delta = 0;
} else {
delta = (Math.abs(dTop) <= Math.abs(dBottom)) ? dTop : dBottom;
}
break;
}
Relevant parts of my code:
createCircleContainers() snippet:
const circleContainer = this.scene.add
.container(xPos, yPos)
.setSize(circle.width, circle.height)
.setDepth(1006)
.add(circle)
circleContainer.isScrollTo = isScrollTo
circleContainer.name = `circle_container_${i}`
Add scrollable panel
this.journeyScrollablePanel = new RexUIScrollablePanel(this.scene, this.width / 2, 255, 400, 250, 'aqua', {}, 'sizer')
this.scene.add.existing(this.journeyScrollablePanel)
const circleContainers = this.createCircleContainers()
this.journeyScrollablePanel.update(circleContainers, true, true, false, null)
this.journeyScrollablePanel.update is
public update(elementArr: any[], useXAsLeftPadding: boolean, isScrollToItem: boolean, isAddNewLines: boolean, config: any): void {
const sizer = this.getSizerElement()
sizer.clear(true)
const scrollablePanelConfig = {
padding: {
top: config && config.paddingTop != null ? config.paddingTop : 0,
left: config && config.paddingLeft != null ? config.paddingLeft : 0,
bottom: config && config.paddingBottom != null ? config.paddingBottom : 0,
right: config && config.paddingRight != null ? config.paddingRight : 0,
},
align: config && config.align ? config.align : 'left',
}
elementArr.forEach((element): void => {
if (useXAsLeftPadding) {
scrollablePanelConfig.padding.left = element.x
}
if (isAddNewLines && sizer instanceof FixWidthSizer) {
sizer.addNewLine()
}
sizer.add(element, scrollablePanelConfig)
})
this.layout()
// https://rexrainbow.github.io/phaser3-rex-notes/docs/site/ui-scrollablepanel/#scroll-to-child
if (isScrollToItem) {
const firstScrollToElement = elementArr.find((el) => el.isScrollTo)
if (firstScrollToElement) {
this.scrollToChild(firstScrollToElement)
}
}
}
Can you help?
The way I've tried to solve this is to manually add the required methods: see the forked scrollTo
rexUI demo here.
I'd love a better solution though.
for (var i = 0; i < 50; i++) {
var name = `item-${i}`;
var label = scene.rexUI.add.label({
background: scene.rexUI.add.roundRectangle({
color: COLOR_PRIMARY
}),
text: scene.add.text(0, 0, name),
space: { left: 10, right: 10, top: 10, bottom: 10 },
name: name,
});
let container = scene.add.container(0, 0, label).setSize(label.width, label.height);
container.getTopLeft = function (output) {
if (!output) {
output = new Phaser.Math.Vector2();
}
output.x = this.x - this.displayWidth * this.originX;
output.y = this.y - this.displayHeight * this.originY;
return output;
};
container.getBottomLeft = function (output) {
if (!output) {
output = new Phaser.Math.Vector2();
}
output.x = this.x - this.displayWidth * this.originX;
output.y = this.y + this.displayHeight * (1 - this.originY);
return output;
};
container.name = name;
panel.add(container, { expand: true });
}
Sorry for missing this thread. I had rewrote some logic of scrollToChild method, to avoid using built-in method to get top-left/bottom-left position. Thus you don't have to add extra method at all. NPM package will be upgraded at end of this month.
Hi, I'm looking for functionality similar to anchor tag in your scrollablePanel. Basically, I need the scrollable panel to automatically scroll down to a textElement added using "this.scene.rexUI.add.BBCodeText(...)". I've tried doing this manually by getting the
y
coordinate of the target scrollTo element and getting a scroll percentage based ontargetY/scrollablePanel.height
, but this doesn't get me exactly where I want. Just like anchor tag, I want it to scroll to where the target element begins, just to reveal the full target element, and not past it to show content below.Which calls:
In this example: it should scroll to "Objective: Scenario 4" so that it's fully visible:
In the result of the code, however, it's scroll way past it: