Angular 10 - 拖动时不触发(点击)功能
Angular 10 - Not to trigger (click) function on dragging
我有一个 div,带有这样的 openlayers 地图:
<div id="map" (click)="getInfo($event)" class="map"></div>
我使用鼠标拖动在地图上导航,每次我这样做时都会触发 getInfo
功能。我只希望它在我单击地图时触发,而不是在导航时触发。
可能吗?谢谢!
https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event
click fires after the mousedown and mouseup events, in that order.
您可能必须创建设置某种时间间隔的 mousedown 和 mouseup 处理程序。
mousedown 将启动一些计时器...即 200ms,如果在该时间间隔内触发了 mouseup 事件,您可以将其视为单击并调用 getInfo 并将事件传递给 mouseup
如果 mouseup 事件在该间隔之外触发,则假定它是拖放鼠标操作并忽略它。
@ViewChild('map') mapElem: ElementRef;
ngAfterViewInit() {
const mousedown$ = fromEvent(this.mapElem.nativeElement, 'mousedown');
const mouseup$ = fromEvent(this.mapElem.nativeElement, 'mouseup');
mousedown$.subscribe(e => {
const clickTimer$ = timer(200);
mouseup$.pipe(takeUntil(clickTimer$)).subscribe(e => this.getInfo(e));
});
}
getInfo(e) {
console.log('click')
}
https://stackblitz.com/edit/angular-sobuqt
检查我制作的这个演示的控制台输出,你会看到你想要的行为。
您可以结合使用 click
和 mousedown
事件绑定来处理这种情况。这可以防止在拖动地图时触发点击事件。
<div id="map" (mousedown)="check($event)" (click)="getInfo($event)" class="map"></div>
在你的 .ts 代码上,
click: boolean = false;
check() {
window.setTimeout(this.startCheck(), 1000);
}
startCheck() {
this.click = true;
}
getInfo(event) {
if (this.click) {
// handle the real click event
}
}
我在检测拖动与点击时遇到了同样的问题,但不想使用定时事件。如果点击太慢它会考虑拖动如果拖动太快它会考虑点击。
相反,我使用了鼠标定位。如果 x,y 位置在鼠标按下和单击(鼠标弹起时触发)之间发生变化,则表示拖动,否则表示单击。
伪代码:
<div (mousedown)="onMouseDown($event)" (click)="onClick($event)"></div>
.ts 文件:
mousePosition = {
x: 0,
y: 0
};
mouseDown($event: MouseEvent) {
this.mousePosition.x = $event.screenX;
this.mousePosition.y = $event.screenY;
}
onClick($event: PointerEvent) {
if (
this.mousePosition.x === $event.screenX &&
this.mousePosition.y === $event.screenY
) {
// Execute Click
}
}
不要这样!
其他答案给出了关于如何在不处理拖放的情况下完成处理点击的直接答案。他们很好。但是需要考虑的是用户体验。当您区分单击和拖放时,您将依赖于用户设备的工作流畅程度以及用户如何操作鼠标。
例如:如果在电脑、笔记本电脑或智能手机上会有延迟,延迟解决方案将导致点击而不是拖动被触发。在其他情况下,不会触发点击,但会触发带有用户无法逃脱的严重状态冲突的拖动。
此外,人们在点击时往往会用鼠标做小动作。界面会在这些情况下触发拖拽。或者,有时人们想要拖动但会单击并导航到另一个页面。他们需要回去。很烦人。
总而言之 - 同时处理同一元素上的单击和拖放操作是非常糟糕的用户体验。有时无法避免。
但是每次都可以,您应该使用各种变通方法避免在 UI 的同一部分上单击和拖动。
这个问题有三种正确的解法:
1) 使用单独的视图重新排序项目s(有点烦人,因为它重复了列表):
2) 使用拖动处理程序(拖动处理程序可以很小,所以用户仍然可以在它外面单击并导航到其他地方,即使他不想这样做):
3) 使用开关启用拖动(最佳解决方案)。请注意,在下面的模型中,拖动处理程序应该被隐藏,因为复选框已关闭。使用这种方法时,整行都可以拖动,从而更容易拖放。仍然可以显示拖动处理程序以指示 UI 中的变化(嘿用户,现在您可以拖放了!)
我有一个 div,带有这样的 openlayers 地图:
<div id="map" (click)="getInfo($event)" class="map"></div>
我使用鼠标拖动在地图上导航,每次我这样做时都会触发 getInfo
功能。我只希望它在我单击地图时触发,而不是在导航时触发。
可能吗?谢谢!
https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event
click fires after the mousedown and mouseup events, in that order.
您可能必须创建设置某种时间间隔的 mousedown 和 mouseup 处理程序。
mousedown 将启动一些计时器...即 200ms,如果在该时间间隔内触发了 mouseup 事件,您可以将其视为单击并调用 getInfo 并将事件传递给 mouseup
如果 mouseup 事件在该间隔之外触发,则假定它是拖放鼠标操作并忽略它。
@ViewChild('map') mapElem: ElementRef;
ngAfterViewInit() {
const mousedown$ = fromEvent(this.mapElem.nativeElement, 'mousedown');
const mouseup$ = fromEvent(this.mapElem.nativeElement, 'mouseup');
mousedown$.subscribe(e => {
const clickTimer$ = timer(200);
mouseup$.pipe(takeUntil(clickTimer$)).subscribe(e => this.getInfo(e));
});
}
getInfo(e) {
console.log('click')
}
https://stackblitz.com/edit/angular-sobuqt
检查我制作的这个演示的控制台输出,你会看到你想要的行为。
您可以结合使用 click
和 mousedown
事件绑定来处理这种情况。这可以防止在拖动地图时触发点击事件。
<div id="map" (mousedown)="check($event)" (click)="getInfo($event)" class="map"></div>
在你的 .ts 代码上,
click: boolean = false;
check() {
window.setTimeout(this.startCheck(), 1000);
}
startCheck() {
this.click = true;
}
getInfo(event) {
if (this.click) {
// handle the real click event
}
}
我在检测拖动与点击时遇到了同样的问题,但不想使用定时事件。如果点击太慢它会考虑拖动如果拖动太快它会考虑点击。
相反,我使用了鼠标定位。如果 x,y 位置在鼠标按下和单击(鼠标弹起时触发)之间发生变化,则表示拖动,否则表示单击。
伪代码:
<div (mousedown)="onMouseDown($event)" (click)="onClick($event)"></div>
.ts 文件:
mousePosition = {
x: 0,
y: 0
};
mouseDown($event: MouseEvent) {
this.mousePosition.x = $event.screenX;
this.mousePosition.y = $event.screenY;
}
onClick($event: PointerEvent) {
if (
this.mousePosition.x === $event.screenX &&
this.mousePosition.y === $event.screenY
) {
// Execute Click
}
}
不要这样!
其他答案给出了关于如何在不处理拖放的情况下完成处理点击的直接答案。他们很好。但是需要考虑的是用户体验。当您区分单击和拖放时,您将依赖于用户设备的工作流畅程度以及用户如何操作鼠标。
例如:如果在电脑、笔记本电脑或智能手机上会有延迟,延迟解决方案将导致点击而不是拖动被触发。在其他情况下,不会触发点击,但会触发带有用户无法逃脱的严重状态冲突的拖动。
此外,人们在点击时往往会用鼠标做小动作。界面会在这些情况下触发拖拽。或者,有时人们想要拖动但会单击并导航到另一个页面。他们需要回去。很烦人。
总而言之 - 同时处理同一元素上的单击和拖放操作是非常糟糕的用户体验。有时无法避免。
但是每次都可以,您应该使用各种变通方法避免在 UI 的同一部分上单击和拖动。
这个问题有三种正确的解法:
1) 使用单独的视图重新排序项目s(有点烦人,因为它重复了列表):
2) 使用拖动处理程序(拖动处理程序可以很小,所以用户仍然可以在它外面单击并导航到其他地方,即使他不想这样做):
3) 使用开关启用拖动(最佳解决方案)。请注意,在下面的模型中,拖动处理程序应该被隐藏,因为复选框已关闭。使用这种方法时,整行都可以拖动,从而更容易拖放。仍然可以显示拖动处理程序以指示 UI 中的变化(嘿用户,现在您可以拖放了!)