Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Displaying image in tooltip is giving me a flickering effect when hovered over the content

I am using Angular here.I am trying to display an image/video inside the tooltip when hovered over the certain content. However, when I hover over the content, the image gives a flickering effect before being rendered. The transition isn't as smooth as when I put text in place of the image. How do I fix it?

I am trying to set the image src in input to the tooltip component. I have a directive which is generating the tooltip content. Code here is as:

app.component.html

<button awesomeTooltip="Hello World!"  image="https://imgplaceholder.com/420x320/ff7f7f/333333/fa-image">Hi there, I have a tooltip</button>

tooltip.component.ts

import { Component, Input } from '@angular/core';
import { animate, style, transition, trigger } from '@angular/animations';

@Component({
  selector: 'awesome-tooltip',
  styleUrls: ['./tooltip.component.css'],
  templateUrl: './tooltip.component.html',
  animations: [
    trigger('tooltip', [
      transition(':enter', [
        style({ opacity: 0 }),
        animate(300, style({ opacity: 1 })),
      ]),
      transition(':leave', [
        animate(300, style({ opacity: 0 })),
      ]),
    ]),
  ],
})
export class AwesomeTooltipComponent {

  @Input() image=''
  @Input() text = '';
}

tooltip.component.html

<div @tooltip>
   <img [src]="image" width="20px" height="30px">
   <!-- Hello -->
</div>

tooltip.directive.ts

import { ComponentRef, Directive, ElementRef, HostListener, Input, OnInit } from '@angular/core';
import { Overlay, OverlayPositionBuilder, OverlayRef } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal';

import { AwesomeTooltipComponent } from './tooltip.component';

@Directive({ selector: '[awesomeTooltip]' })
export class AwesomeTooltipDirective implements OnInit {

  @Input('awesomeTooltip') text = '';
  @Input('image') image = '';
  private overlayRef: OverlayRef;

  constructor(private overlay: Overlay,
              private overlayPositionBuilder: OverlayPositionBuilder,
              private elementRef: ElementRef) {
  }

  ngOnInit(): void {
    const positionStrategy = this.overlayPositionBuilder
      .flexibleConnectedTo(this.elementRef)
      .withPositions([{
        originX: 'center',
        originY: 'top',
        overlayX: 'center',
        overlayY: 'bottom',
        offsetY: -8,
      }]);

    this.overlayRef = this.overlay.create({ positionStrategy });
  }

  @HostListener('mouseenter')
  show() {
    const tooltipRef: ComponentRef<AwesomeTooltipComponent>
      = this.overlayRef.attach(new ComponentPortal(AwesomeTooltipComponent));
    tooltipRef.instance.text = this.text;
    tooltipRef.instance.image = this.image;
  }

  @HostListener('mouseout')
  hide() {
    this.overlayRef.detach();
  }
}

The stackblitz link is here:

I result I am looking for is:

  • I should be able to send image url from the tag over which, I want to show the tooltip.
  • The tooltip should show that image inside it.
like image 463
Udit Gogoi Avatar asked Oct 19 '25 22:10

Udit Gogoi


1 Answers

This is how the overlay is setup:

  • when you hover on button, overlay becomes visible
  • when you move to anything other than the button, the overlay hides

The flickering you experience is due to a never-resolving situation:

  1. When you hover on the bottom part of the button, the overlay becomes visible
  2. But since the overlay starts from the middle of the button, technically you are now hovering on the overlay (and no longer over the button), so the overlay becomes hidden
  3. As soon as overlay becomes hidden, you are back to point #1 above...

This goes on and on, which is why you experience flickering effect.

for solution, add the following code to your tooltip.component.css, which place the overlay under the button, so that this recursive flickering doesn't happen:

::ng-deep .cdk-overlay-connected-position-bounding-box{top:60px !important; position:absolute;}

UPDATE: for a bigger button, the top value can be changed to make sure that the overlay starts from under the button and that there is no overlap. demo here

like image 150
Akber Iqbal Avatar answered Oct 22 '25 13:10

Akber Iqbal



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!