Home > OS >  Angular, mouseover speed is choppy?
Angular, mouseover speed is choppy?

Time:06-21

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?

https://stackblitz.com/edit/angular-l2wgqt?file=src/app/app.component.ts

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)">
<h2>This is a Panel</h2>
<p>Hello my darling</p>
</div>

<div id="first">asdasdasdasd</div>

CodePudding user response:

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:

  • Don't perform the same element query multiple times in one function, but perform the lookup once and store it in a variable. Possibly, you can even perform the lookup just once on component initialization, but that depends on the further logic of your component.
  • Make sure to set 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()"
  
>
  <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

CodePudding user response:

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...

  • try to avoid calling console.log always (include a condition of some kind)
  • instead of calling this method every time this.el.nativeElement.querySelector('#first') assign it to a variable en reuse it
let 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 onm ouseover

  • Related