Issue
I have an editor in which the user can create a banner the user can drag the element in any position he/she wants inside a banner, the element has a tooltip, on hover, it should show the tooltip positioned on the side where the space is larger than the rest (top, left, bottom, right) and the tooltip should never go outside the container no matter what.
HTML
<div id="banner-container" class="banner-container">
<span
(cdkDragReleased)="onCircleButtonDragEnd($event)"
id="point-button"
class="point-button"
cdkDragBoundary=".banner-container"
cdkDrag
[style.left]="banner.bannerElements.x"
[style.top]="banner.bannerElements.y"
[attr.data-id]="banner.bannerElements.buttonId"
[id]="'button-' + banner.bannerElements.buttonId"
></span>
<span
id="tooltip"
[style.left]="banner.bannerElements.x"
[style.top]="banner.bannerElements.y"
[attr.data-id]="banner.bannerElements.tooltipId"
[id]="'button-' + banner.bannerElements.tooltipId"
>
Szanujemy Twoją prywatność
</span>
</div>
TS
banner = {
buttonId: 11,
tooltipId: 2,
x: 0,
y: 0
};
onCircleButtonDragEnd(event) {
const container = event.currentTarget as HTMLElement;
const containerWidth = container.clientWidth;
const containerHeight = container.clientHeight;
this.banner.y =
((event.clientX - container.getBoundingClientRect().left) /
containerWidth) *
100;
this.banner.y =
((event.clientY - container.getBoundingClientRect().top) /
containerHeight) *
100;
}``
CSS
.point-button {
cursor: pointer;
display: block;
width: 24px;
height: 24px;
border: 2px solid rgb(179, 115, 188);
background-color: rgb(255, 255, 255);
background-image: none;
border-radius: 100%;
position: relative;
z-index: 1;
box-sizing: border-box;
}
.point-button:active {
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
}
.banner-container {
width: 350px;
height: 200px;
max-width: 100%;
border: dotted #ccc 2px;
}
.tooltip {
width: fit-content;
height: 50px;
border: 2px #ccc solid;
display: none;
}
.point-button:hover + .tooltip {
display: block;
}`
**
LIVE DEMO
** : DEMO
**
Update:
** Without using any library
Solution
TLDR; StackBlitz demo.
You can create a function that does the math and logic of determining the top
and left
properties of the tooltip position. Then you can easily apply them using [ngStyle]
:
<div #container class="banner-container">
<span #element class="point-button" cdkDrag
[cdkDragBoundary]="container"
(cdkDragReleased)="updateTooltipStyle()"
></span>
<span #tooltip class="tooltip" [ngStyle]="tooltipStyle">
This is a tooltip :-)
</span>
</div>
export class CdkDragDropHorizontalSortingExample implements AfterViewInit {
@ViewChild('container') container!: ElementRef;
@ViewChild('element') element!: ElementRef;
@ViewChild('tooltip') tooltip!: ElementRef;
tooltipStyle = {};
ngAfterViewInit() {
this.updateTooltipStyle();
}
updateTooltipStyle() {
const parent = this.container.nativeElement.getBoundingClientRect();
const element = this.element.nativeElement.getBoundingClientRect();
const tooltip = this.tooltip.nativeElement.getBoundingClientRect();
const spaceLeft = element.left - parent.left;
const spaceRight = parent.right - element.right;
const spaceTop = element.top - parent.top;
const spaceBottom = parent.bottom - element.bottom;
const spaceX = Math.max(spaceLeft, spaceRight) - tooltip.width;
const spaceY = Math.max(spaceTop, spaceBottom) - tooltip.height;
let tooltipTop, tooltipLeft;
if (spaceX > spaceY) {
tooltipLeft = spaceLeft > spaceRight
? element.left - parent.left - tooltip.width - MARGIN
: element.right - parent.left + MARGIN;
tooltipTop = Math.min(Math.max(0, (element.top - parent.top) + (element.height - tooltip.height) / 2), parent.height - tooltip.height);
} else {
tooltipTop = spaceTop > spaceBottom
? element.top - parent.top - tooltip.height - MARGIN
: element.bottom - parent.top + MARGIN;
tooltipLeft = Math.min(Math.max(0, (element.left - parent.left) + (element.width - tooltip.width) / 2), parent.width - tooltip.width);
}
this.tooltipStyle = {
left : `${tooltipLeft}px`,
top : `${tooltipTop}px`,
width : `${tooltip.width}px`
};
}
}
Here's a working StackBlitz demo.
Answered By - BizzyBob
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.