javascript - 与角度叠加 cdk 全球定位策略和在灰色区域的任何位置放置元素有关的问题
问题描述
我正在学习教程并实现了拖放,但是我面临两个问题
关于使用新的 GlobalPositionStrategy(document); 在draggable 文件夹下的draggable-helper.directive.ts文件中,显示错误说明 Expected 0 arguments but got 1 ,因此我无法获得预期的结果,如此链接 https://stackblitz.com/edit/ draggable-part-6-4lwvqa?file=app/app.component.html
我可以拖放灰色区域中的框,但问题是,每次拖放时,我拖放的框都位于灰色区域的同一顶部、左侧位置。
期望盒子可以在灰色区域内的任何地方拖放(一旦我拖放,之后我就可以将盒子移动到任何地方,而期望盒子可以在灰色区域内的任何地方拖放)
dropzone.directive.ts有一个函数isEventInside我尝试调整它但无法解决问题(2)。
拖放如何工作的事件链是,在 hello.component 我们有输出事件 dragStart 和 drop,它们存在于draggable.directive.ts和dropzone.directive.ts中。
Stackblitz 链接 https://stackblitz.com/edit/angular-1gjtab?file=src/app/hello.component.html
可拖动的.directive
import { Directive, EventEmitter, HostBinding, HostListener, Output,
ElementRef } from '@angular/core';
@Directive({
selector: '[appDraggable],[appDroppable]'
})
export class DraggableDirective {
@HostBinding('class.draggable') draggable = true;
pointerId?: number;
@HostBinding('attr.touch-action') touchAction = 'none';
@Output() dragStart = new EventEmitter<PointerEvent>();
@Output() dragMove = new EventEmitter<PointerEvent>();
@Output() dragEnd = new EventEmitter<PointerEvent>();
@HostBinding('class.dragging') dragging = false;
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);
}
}
dropzone.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 {
@HostBinding('class.dropzone-activated') activated = false;
@HostBinding('class.dropzone-entered') entered = false;
@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);
}
this.activated = false;
this.entered = false;
}
private onInnerDragStart() {
this.activated = true;
this.entered = true;
}
private onInnerDragEnd(event: PointerEvent) {
if (!this.entered) {
this.remove.emit(event);
}
this.activated = false;
this.entered = false;
}
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;
}
}
你好组件
<div #parentparent id="toget" class="dropzone"
[ngStyle]="{'width':'400px', 'border':'1px solid black', 'height':'340px'
'margin-top':'120px'}" appMovableArea appDropzone
(drop)="move(currentBox, dropzone1)">
<div class="box" appMovable
*ngFor="let existingZone of existingDroppedItemZoneIn"
(dragStart)="currentBox = existingZone"
(dragEnd)="onDragEnd($event,box)" #childchild>
{{ existingZone.main }}
</div>
<div class="box" *ngFor="let box of dropzone1" appDroppable
(dragStart)="currentBox = box" appMovable
(dragEnd)="onDragEnd($event,box)" #childchild>
{{ box.dis.dis }}
</div>
</div>
应用程序组件
<div *ngFor="let room of rooms"
class="box"
appDroppable
(dragStart)="currentBox = room">
{{ room.dis }}
<div class="box box-helper" *appDraggableHelper>{{ room.dis }}</div>
</div>
<hello [roomsFloorZone]='zonesToBePassed'
[currentBoxFloorZone]='currentBox'
[existingDroppedItem] = 'droppedItem'
(floorToParent)="updateFloorRooms($event)"
[ngStyle]="{'margin- top':'90px'}">
</hello>
droppable.directive
import { Directive, HostListener } from '@angular/core';
import { DroppableService } from './droppable.service';
@Directive({
selector: '[appDroppable]'
})
export class DroppableDirective {
constructor(private droppableService: DroppableService) { }
@HostListener('dragStart', ['$event'])
onDragStart(event: PointerEvent): void {
this.droppableService.onDragStart(event);
}
@HostListener('dragMove', ['$event'])
onDragMove(event: PointerEvent): void {
this.droppableService.onDragMove(event);
}
@HostListener('dragEnd', ['$event'])
onDragEnd(event: PointerEvent): void {
this.droppableService.onDragEnd(event);
}
}
解决方案
我不知道我是否正确。由于讨论很长,我开始了一个不同的答案......
用于 DnD 的两个不同 Stackblitz 版本以及来自 Angular 的不同版本。一对一的说法是使用 Angular 5.2.4,而不起作用的是使用 8.1.4。
我猜初始化应该是这样的
private positionStrategy = new GlobalPositionStrategy();
...
ngOnInit(): void {
this.positionStrategy.attach(...);
正确使用请参考
我看到的另一个问题是 DnD 图像设置不正确。您需要设置它,因为 drop 已经是鼠标光标指向的位置。
推荐阅读
- google-apps-script - Google 表格的解决方法访问权限
- python - 访问列表中具有特定属性的对象
- gradle - Gradle 的 Groovy 语法:项目
- c - 为什么我们需要在 C 中为数组使用 malloc() 或任何其他动态内存?
- azure-active-directory - Azure IoTHub 用于访问遥测和心跳数据的最低特权角色
- c - 运行 eclipse CDT 名称样式检查无头
- html - 发送短信链接正文不显示带有等号“=”的网址
- python - 当作为参数传递或返回时,Numpy 如何处理内存分配?
- c# - c#如何在包含许多数据表的数据集中查找重复记录?
- php - 无法使用 PHP exec 运行 gsutil