When developing the blink-mind-react mind map control, there was a requirement that when clicking to expand and collapse a node, the position of the icon to expand and collapse (relative to the viewport) would not change.
The mind map component is inside the DragScroll component because the mind map needs to be able to be dragged to any area of the viewport for viewing. When developing mind mapping components, the layout is Flex. When click open or folded button, change the size of the entire control, and the effect that I want is to click the position of the buttons on the visual effect can’t have a mobile, otherwise, if you click on the button, button found moved to another location (because the layout is rearrangement), the user experience will be very poor.
In order to solve the above problem, a solution is to call a function to adjust the scroll value of the viewBox in the DragScroll control to the appropriate position after the button is clicked, so that the position of the button is not changed visually.
Based on the above scheme, two functions are encapsulated in the DragScroll component:
-
SetViewBoxScroll is adjusting the scroll using absolute coordinates
-
SetViewBoxScrollDelta is an scroll adjustment using relative coordinates
setViewBoxScroll = (left: number, top: number) => {
if(this.viewBox) { this.viewBox.scrollLeft = left; this.viewBox.scrollTop = top; }};setViewBoxScrollDelta = (deltaLeft: number, deltaTop: number) => {
if(this.viewBox) { this.viewBox.scrollLeft += deltaLeft; this.viewBox.scrollTop += deltaTop; }};Copy the code
Passed to child components through calls in the Render function
{this.props.children(
this.setViewBoxScroll,
this.setViewBoxScrollDelta
)}
Copy the code
In this way, the component can get the two functions through props and call either of them when it needs to do the scroll adjustment it needs.
For example, in NodeWidget, the node component of the mind map, setViewBoxScrollDelta function is used to adjust the scroll value of the DragScroll component to ensure that the visual position of the node remains unchanged during expansion or collapse.
componentDidUpdate( prevProps: Readonly<MindNodeWidgetProps>, prevState: Readonly<MindNodeWidgetState>, snapshot? : any ): void {if (this.needRelocation) {
let newRect = this.collapseIcon.getBoundingClientRect();
this.props.setViewBoxScrollDelta(
newRect.left - this.oldCollapseIconRect.left,
newRect.top - this.oldCollapseIconRect.top
);
this.needRelocation = false;
}
this.layoutSubLinks();
}
Copy the code