i would like to get this in an Angular4 Component without using Jquery.
I need to show an overlay div with animation based on the mouse direction, both mouseover and mouseout. I tried to rewrite the example code in my component but i cannot get the width and height of the event.target.
My div:
<div (mouseover)='showOverlay($event)'>div to hover</div>
Component:
export class MyComponent implements OnInit {
constructor(private _el: ElementRef) {
}
ngOnInit() {
}
showOverlay(e) {
const target = e.target;
console.log(target._el.nativeElement); // Returns undefined
console.log(target.nativeElement); // Returns undefined
console.log(target.nativeElement.width); // Error
console.log(target._el.nativeElement.width); // Error
}
}
Any idea?
Thank you
I like this effect, so I made a component with angular animations: https://stackblitz.com/edit/angular-fftwpg.
import { Component, HostListener } from '@angular/core';
import { AnimationEvent } from '@angular/animations';
import {
trigger,
state,
style,
animate,
transition
} from '@angular/animations';
const animateIn = '0.15s ease-in';
const animateOut = '0.25s ease-out';
const styleIdle = { transform: 'translate3d(0, 0, 0)' };
const styleTop = { transform: 'translate3d(0, -100%, 0)' };
const styleRight = { transform: 'translate3d(100%, 0, 0)' };
const styleBottom = { transform: 'translate3d(0, 100%, 0)' };
const styleLeft = { transform: 'translate3d(-100%, 0, 0)' };
export const HoverContainerAnimations = [
trigger('hover', [
state('*', style(styleIdle)),
transition('* => in-left', [
style(styleLeft), animate(animateIn)
]),
transition('* => in-right', [
style(styleRight), animate(animateIn)
]),
transition('* => in-top', [
style(styleTop), animate(animateIn)
]),
transition('* => in-bottom', [
style(styleBottom), animate(animateIn)
]),
transition('* => out-right', [
animate(animateOut, style(styleRight))
]),
transition('* => out-left', [
animate(animateOut, style(styleLeft))
]),
transition('* => out-top', [
animate(animateOut, style(styleTop))
]),
transition('* => out-bottom', [
animate(animateOut, style(styleBottom))
]),
])
];
@Component({
// tslint:disable-next-line:component-selector
selector: 'hover-container',
template: `
<ng-content></ng-content>
<div class="overlay"
*ngIf="state"
[@hover]="state"
(@hover.done)="onDone($event)">
<ng-content select="[overlay]"></ng-content>
</div>`,
styleUrls: ['./hover-container.component.css'],
animations: HoverContainerAnimations,
})
export class HoverContainerComponent {
state;
@HostListener('mouseenter', ['$event'])
@HostListener('mouseleave', ['$event'])
onHover(event: MouseEvent) {
const direction = event.type === 'mouseenter' ? 'in' : 'out';
const host = event.target as HTMLElement;
const w = host.offsetWidth;
const h = host.offsetHeight;
const x = (event.pageX - host.offsetLeft - (w / 2)) * (w > h ? (h / w) : 1);
const y = (event.pageY - host.offsetTop - (h / 2)) * (h > w ? (w / h) : 1);
const states = ['top', 'right', 'bottom', 'left'];
const side = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4;
this.state = `${direction}-${states[side]}`;
}
onDone(event: AnimationEvent) {
this.state = event.toState.startsWith('out-') ? null : this.state;
}
}
I think it would be better to write a Directive
so you can 'reuse' it for each <div>
.
Directive:
@Directive({
selector: '[over]'
})
export class OverDirective {
constructor(private elementRef: ElementRef) {
}
@HostListener('mouseover', ['$event'])
onOver(event: MouseEvent): void {
console.log(this.elementRef.nativeElement.offsetHeight)
}
}
HTML:
<div over id="myDiv">div to hover</div>
If you still want to access to the element from inside the component via template variable:
HTML
<div id="div2" (mouseover)="onMouseOver($event, toto)" #toto>an other div to hover</div>
Typescript
onMouseOver(event, elem)
{
console.log(elem.offsetHeight);
}
Plunker
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With