由于在同一元素的多个指令中使用了相同的鼠标事件,因此指令没有响应 [英] Directive not responding due to same mouse events being used in multiple directives on same element

查看:69
本文介绍了由于在同一元素的多个指令中使用了相同的鼠标事件,因此指令没有响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个功能,可以将框拖放到灰色区域(请参阅stackblitz链接) 拖放框后,只能通过单击框的粉红色将其移动到灰色区域内.

I have a feature where box can be dragged and dropped into the grey area(Please refer to the stackblitz link) Once the box is dragged and dropped , the box can only be moved within the grey area by clicking on the pink color of the box.

还增加了调整大小功能,因此可以调整框的大小.

Resizing functionality has also been added, so the box can be resized.

在添加resize指令之前,该框只能在灰色区域内移动,但是在我们调整大小后添加添加了resize指令后,该框开始移出灰色区域,问题是该框不应移出灰色区域调整大小后的区域

Before resize directive was added the box can only be moved within grey area but after adding adding the resize directive when we resize, the box starts moving out of the grey area , the issue is the box should not move out of the grey area when resizing is done

Stackblitz链接

Stackblitz link

https://stackblitz.com/edit/angular-rgeq2p?file=src/app/hello.component.html

hello.component.html [在此框上应用了指令和指令]

hello.component.html [ has the box and directives applied on the box ]

<div appMovableArea appDropzone (drop)="move(currentBox, dropzone1)">
<div *ngFor="let box of dropzone1"
      appDroppable
     (dragStart)="currentBox = box"
      appMovable
      resize>
    {{ box.dis }}
</div>
</div>

其中该框具有(dragStart)输出事件发射器,该发射器已绑定到draggable指令([appDroppable + draggable],对于 移动功能appMovable,appMovableArea指令存在).然后使用Droppable.service.ts

where the box has (dragStart) output event emitter which is bound to draggable directive([appDroppable + draggable] and for the move functionality appMovable, appMovableArea directives are there) .And the events are shared among directives using Droppable.service.ts

(放置)是使用以下命令应用于灰色区域的输出事件发射器 dropzone [ appDropzone ]指令

The (drop) is an output event emitter applied on grey area using dropzone[appDropzone] directive

import { Directive, ElementRef, EventEmitter, HostBinding, HostListener, 
    OnInit, Output, SkipSelf } from '@angular/core';
import { DroppableService } from './droppable.service';

@Directive({
     selector: '[appDropzone]',
     providers: [DroppableService]
    })
export class DropzoneDirective implements OnInit {

     @Output() drop = new EventEmitter<PointerEvent>();
     @Output() remove = new EventEmitter<PointerEvent>();
     private clientRect: ClientRect;

constructor(@SkipSelf() private allDroppableService: DroppableService,
              private innerDroppableService: DroppableService,
              private element: ElementRef) { }

ngOnInit(): void {
        this.allDroppableService.dragStart$.subscribe(() => 
        this.onDragStart());
        this.allDroppableService.dragEnd$.subscribe(event => 
        this.onDragEnd(event));

        this.allDroppableService.dragMove$.subscribe(event => {
          if (this.isEventInside(event)) {
        this.onPointerEnter();
      } else {
        this.onPointerLeave();
      }
     });
        this.innerDroppableService.dragStart$.subscribe(() => 
        this.onInnerDragStart());
        this.innerDroppableService.dragEnd$.subscribe(event => 
        this.onInnerDragEnd(event));
}

private onPointerEnter(): void {
     if (!this.activated) {
      return;
     }
     this.entered = true;
     }

private onPointerLeave(): void {
        if (!this.activated) {
         return;
      }
     this.entered = false;
     }

private onDragStart(): void {
       this.clientRect = this.element.nativeElement.getBoundingClientRect();
       this.activated = true;
      }

private onDragEnd(event: PointerEvent): void {
        if (!this.activated) {
         return;
      }
      if (this.entered) {
        this.drop.emit(event);
      }
     }

private onInnerDragStart() {
    this.activated = true;
    this.entered = true;
    }

private onInnerDragEnd(event: PointerEvent) {
    if (!this.entered) {
      this.remove.emit(event);
    }
  }

private isEventInside(event: PointerEvent) {
    return event.clientX >= this.clientRect.left &&
      event.clientX <= this.clientRect.right &&
      event.clientY >= this.clientRect.top &&
      event.clientY <= this.clientRect.bottom;
  }
}

然后在(dragStart)框上显示输出事件发射器,该事件出现在 draggable 指令[ appDraggable ]中,用于侦听指针下降事件

Then on the box (dragStart) output event emitter which is present indraggable directive[appDraggable] which listens for pointerdown events

import { Directive, EventEmitter, HostBinding, HostListener, Output, 
ElementRef } from '@angular/core';
@Directive({
 selector: '[appDraggable],[appDroppable]'
})
export class DraggableDirective {
 @Output() dragStart = new EventEmitter<PointerEvent>();
 @Output() dragMove = new EventEmitter<PointerEvent>();
 @Output() dragEnd = new EventEmitter<PointerEvent>();

 constructor(public element: ElementRef) {}

 @HostListener('pointerdown', ['$event'])
   onPointerDown(event: PointerEvent): void {
    if (event.button !== 0) {
    return;
   }
   this.pointerId = event.pointerId;
   this.dragging = true;
   this.dragStart.emit(event); 
   }

 @HostListener('document:pointermove', ['$event'])
    onPointerMove(event: PointerEvent): void {
     if (!this.dragging || event.pointerId !== this.pointerId) {
     return;
    } 
    this.dragMove.emit(event);
    }

 @HostListener('document:pointercancel', ['$event'])
 @HostListener('document:pointerup', ['$event'])
     onPointerUp(event: PointerEvent): void {
    if (!this.dragging || event.pointerId !== this.pointerId) {
      return;
    }
    this.dragging = false;
    this.dragEnd.emit(event);
    }
   }

可移动指令,用于在灰色区域内保持移动, 轮流使用基于可移动区域指令的计算

Movable directive for maintaining move inside the grey area which in turn uses calculation based from movable-area directive

import { Directive, ElementRef, HostBinding, HostListener, Input } from 
'@angular/core';
import { DraggableDirective } from './draggable.directive';
import { DomSanitizer, SafeStyle } from '@angular/platform-browser';

interface Position {
 x: number;
 y: number;
}

@Directive({
 selector: '[appMovable]'
})
export class MovableDirective extends DraggableDirective {
  @HostBinding('style.transform') get transform(): SafeStyle {
   return this.sanitizer.bypassSecurityTrustStyle(
  `translateX(${this.position.x}px) translateY(${this.position.y}px)`
  );
  }

  @HostBinding('class.movable') movable = true;
  position: Position = {x: 0, y: 0};
  private startPosition: Position;
  @Input('appMovableReset') reset = false;

constructor(private sanitizer: DomSanitizer, public element: ElementRef) {
   super(element);
 }

@HostListener('dragStart', ['$event'])
   onDragStart(event: PointerEvent) {
     this.startPosition = {
     x: event.clientX - this.position.x,
     y: event.clientY - this.position.y
 }
 }

@HostListener('dragMove', ['$event'])
   onDragMove(event: PointerEvent) {
    this.position.x = event.clientX - this.startPosition.x;
    this.position.y = event.clientY - this.startPosition.y;
 }

@HostListener('dragEnd', ['$event'])
   onDragEnd(event: PointerEvent) {
    if (this.reset) {
     this.position = {x: 0, y: 0};
 }
 }
}

stackblitz链接中也提供了resize指令. 在styles.css中存在用于resize指令的样式

The resize directive is also present in the stackblitz link. And styles for resize directive are present in styles.css

推荐答案

您可以做的一个小技巧是将'resizing'类添加到resize指令中的元素,并检查该类是否存在于可拖动指令中(如果不存在)它可拖动.我很难获取您的代码,因为它是如此的困难.我不知道你为什么这么复杂.

One small hack you can do is add 'resizing' class to the element in resize directive and check whether that class is present in draggable directive if present do not make it draggable. I can't get your code because it's so difficult. I don't know why you made this so complex.

这篇关于由于在同一元素的多个指令中使用了相同的鼠标事件,因此指令没有响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆