html - 由于在同一元素上的多个指令中使用了相同的鼠标事件,指令没有响应
问题描述
我有一个可以将盒子拖放到灰色区域的功能(请参阅stackblitz链接)一旦盒子被拖放,盒子只能通过点击盒子的粉红色在灰色区域内移动.
还添加了调整大小的功能,因此可以调整框的大小。
在添加resize指令之前,盒子只能在灰色区域内移动,但是在我们调整大小时添加resize指令后,盒子开始移出灰色区域,问题是盒子在调整大小时不应该移出灰色区域已经完成了
Stackblitz 链接
https://stackblitz.com/edit/angular-rgeq2p?file=src/app/hello.component.html
hello.component.html [在盒子上应用了盒子和指令]
<div appMovableArea appDropzone (drop)="move(currentBox, dropzone1)">
<div *ngFor="let box of dropzone1"
appDroppable
(dragStart)="currentBox = box"
appMovable
resize>
{{ box.dis }}
</div>
</div>
盒子有 (dragStart) 输出事件发射器,它绑定到可拖动指令([appDroppable + draggable] 并且对于移动功能 appMovable,appMovableArea 指令在那里)。并且使用 Droppable.service.ts 在指令之间共享事件
( drop)是使用 dropzone [ appDropzone ] 指令应用于灰色区域的输出事件发射器
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;
}
}
然后在可拖动指令 [ appDraggable ] 中存在的框(dragStart)输出事件发射器上,它侦听指针向下事件
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);
}
}
用于在灰色区域内保持移动的可移动指令,而灰色区域又使用基于可移动区域指令的计算
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};
}
}
}
resize 指令也出现在 stackblitz 链接中。调整大小指令的样式存在于 styles.css
解决方案
这是 Drag&Drop 指令的实现,抱歉无法修复您的代码,因为它与调整大小相同:
指示
@Directive({
selector: '[draggable]'
})
class Draggable implements onInit {
private element: HTMLElement;
private handlerNode: HTMLElement;
private data: {x: number, y: number};
@Input('draggable')
private handler: string;
@HostListener('mousedown', ['$event'])
mousedown(e) {
if (e.target === this.handlerNode) {
var rect = this.element.getBoundingClientRect();
this.data = {
x: e.clientX - rect.left,
y: e.clientY - rect.top
};
} else {
delete this.data;
}
}
@HostListener('document:mouseup', ['$event'])
mouseup(e) {
delete this.data;
}
constructor(@Inject(ElementRef) element: ElementRef) {
this.element = element.nativeElement;
}
ngOnInit() {
this.element.classList.add('dragabble');
this.handlerNode = this.element.querySelector(this.handler);
}
@HostListener('document:mousemove', ['$event'])
onPointerMove(e: PointerEvent): void {
if (this.data) {
var x = e.clientX - this.data.x;
var y = e.clientY - this.data.y;
this.element.style.left = x + 'px';
this.element.style.top = y + 'px';
}
}
}
CSS
.dragabble .handler {
position: absolute;
width: calc(100% - 12px);
height: calc(100% - 12px);
left: 6px;
top: 6px;
}
模板:
<div [resize]="toggle" style="left: 100px; top: 50px"
[draggable]="'.handler'">
<div class="handler">xxx</div>
</div>
推荐阅读
- julia - 使用/分发预编译文件
- java - 使用 javacv 1.4.2 在框架中打开图像
- ibm-cloud-infrastructure - 如何检查软层数据类型中的键
- javascript - 将画布数据保存到浏览器
- centos - 如何使用密码安装 vncserver?
- python - Python检查网站是否存在以获取网站列表
- nginx - Nginx 子域:重定向到错误的目录
- python-3.x - PermissionError: [Errno 13] Permission denied:in python 。我也检查了访问权限
- javascript - javascript url.indexOf 等于不包含
- r - 在 R 中为 2 个维度的 3 个变量绘制 3D 图表