I'm trying to create a "tooltip" that follows the mouse around and disappears when it leaves it's location. However, the tooltip created is slow, it doesn't follow my mouse around smoothly and seems choppy. How do I fix this?
TS:
export class AppComponent {
name = 'Angular';
constructor(private el: ElementRef) {}
first(e: { pageX: any; pageY: any }) {
console.log(e.pageX, e.pageY);
this.el.nativeElement.querySelector('#first').style.left =
e.pageX.toString() + 'px';
this.el.nativeElement.querySelector('#first').style.top =
e.pageY.toString() + 'px';
this.el.nativeElement.querySelector('#first').classList.add('show');
}
second(e: { pageX: any; pageY: any }) {
this.el.nativeElement.querySelector('#first').style.left = '0px';
this.el.nativeElement.querySelector('#first').style.top = '0px';
this.el.nativeElement.querySelector('#first').classList.remove('show');
}
}
HTML:
<div (mouseover)="first($event)" (mouseleave)="second($event)"class="place-welcome">
<h2>This is a Panel</h2>
<p>Hello my darling</p>
</div>
<div id="first">asdasdasdasd</div>
Mouseover can be an event that trigger many times in a few seconds, for example the cursor moves 1px while still being over the same htmlElement.
Considering that...
this.el.nativeElement.querySelector('#first') assign it to a variable en reuse itlet first = this.el.nativeElement.querySelector('#first') ;
first.left = e.pageX.toString() + 'px';
first.style.top = e.pageY.toString() + 'px';
first.classList.add('show');
not only it makes your code more readable, it avoids query over and over to get the same result on each call to onmouseover
Instead of using mouseover and mouseleave, use:
mousenter to detect when the mouse enters the div. This is where you display the tooltip.mousemove to detect when the mouse is moved inside the div. This is where you position the tooltip.mouseleave to detect when the mouse leaves the div. This is where you hide the tooltip.In addition:
pointer-events to none for the tooltip; if not, you will get interference from the mouse entering and leaving the tooltip.Putting all of this together, you get the following code:
Component:
import { Component, ElementRef } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
name = 'Angular';
constructor(private el: ElementRef) {}
get tooltip() {
return this.el.nativeElement.querySelector('#first');
}
enter() {
this.tooltip.classList.add('show');
}
move(e: { pageX: number; pageY: number }) {
const tooltipStyle = this.tooltip.style;
tooltipStyle.left = e.pageX + 'px';
tooltipStyle.top = e.pageY + 'px';
}
leave() {
this.tooltip.classList.remove('show');
}
}
Template:
<div
(mouseenter)="enter()"
(mousemove)="move($event)"
(mouseleave)="leave()"
class="place-welcome"
>
<h2>This is a Panel</h2>
<p>Hello my darling</p>
</div>
<div id="first">asdasdasdasd</div>
Stylesheet:
#first {
position: absolute;
opacity: 0;
pointer-events: none;
}
.place-welcome {
width: 100%;
height: 300px;
background: red;
}
.show {
opacity: 1 !important;
}
View on StackBlitz