角度4:在鼠标悬停时显示基于鼠标方向的动画叠加

时间:2017-08-28 08:38:08

标签: angular

我想在不使用Jquery的情况下在Angular4组件中获得this

我需要根据鼠标方向显示带有动画的叠加div,包括mouseover和mouseout。我试图在我的组件中重写示例代码,但我无法获得event.target的宽度和高度。

我的div:

<div (mouseover)='showOverlay($event)'>div to hover</div>

组件:

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

有什么想法吗?

谢谢

2 个答案:

答案 0 :(得分:7)

我喜欢这种效果,所以我制作了一个带角度动画的组件: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;
  }

}

答案 1 :(得分:2)

我认为最好写一个Directive,以便您可以为每个<div>“重复使用”它。

<强>指令:

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

如果您仍想通过模板变量访问组件内部的元素:

<强> HTML

<div id="div2" (mouseover)="onMouseOver($event, toto)" #toto>an other div to hover</div>

<强>打字稿

onMouseOver(event, elem)
  {
    console.log(elem.offsetHeight);
 }

Plunker