我一直试图让一个可拖动的div工作使用Angular 2.我使用
this example from the angular2-examples repo作为起点,只是真正调整代码来解释toRx()方法的删除.该代码有效,但它不考虑mouSEOut事件.这意味着如果我单击一个Draggable div,然后慢慢移动鼠标,div将随鼠标移动.但是如果我移动鼠标太快,则会发送mouSEOut事件而不是mousemove事件,并且拖动停止.
鼠标移动到目前为止,如何触发mouSEOut事件,如何保持拖动?我已尝试将mouSEOut事件流与mousemove one合并,因此mouSEOut事件的处理就像mousemove事件一样,但这不起作用.
我正在使用Angular 2.0.0-beta.12.
import {Component,Directive,HostListener,EventEmitter,ElementRef,OnInit} from 'angular2/core'; import {map,merge} from 'rxjs/Rx'; @Directive({ selector: '[draggable]' }) export class Draggable implements OnInit { mouseup = new EventEmitter(); mousedown = new EventEmitter(); mousemove = new EventEmitter(); mouSEOut = new EventEmitter(); @HostListener('mouseup',['$event']) onMouseup(event) { this.mouseup.emit(event); } @HostListener('mousedown',['$event']) onMousedown(event) { this.mousedown.emit(event); return false; // Call preventDefault() on the event } @HostListener('mousemove',['$event']) onMousemove(event) { this.mousemove.emit(event); } @HostListener('mouSEOut',['$event']) onMouSEOut(event) { this.mouSEOut.emit(event); return false; // Call preventDefault() on the event } constructor(public element: ElementRef) { this.element.nativeElement.style.position = 'relative'; this.element.nativeElement.style.cursor = 'pointer'; map; merge; this.mousedrag = this.mousedown.map(event => { return { top: event.clientY - this.element.nativeElement.getBoundingClientRect().top left: event.clientX - this.element.nativeElement.getBoundingClientRect().left,}; }) .flatMap( imageOffset => this.mousemove.merge(this.mouSEOut).map(pos => ({ top: pos.clientY - imageOffset.top,left: pos.clientX - imageOffset.left })) .takeUntil(this.mouseup) ); } ngOnInit() { this.mousedrag.subscribe({ next: pos => { this.element.nativeElement.style.top = pos.top + 'px'; this.element.nativeElement.style.left = pos.left + 'px'; } }); } } @Component({ selector: 'my-app',template: ` <div draggable> <h1>Hello,World!</h1> </div> `,directives: [Draggable,],}) export class AppComponent { }
我在
RxJs How do deal with document events中找到了答案.问题的关键在于当鼠标悬停在该元素上时,鼠标事件仅发送到元素.所以我们确实希望mousedown事件仅限于特定元素,但我们必须跟踪全局mousemove和mouseup事件.这是新代码.注意在onMouseup和onMousemove上使用@HostListener装饰器将目标指定为document:mouseup和document:mousemove.这是全局事件通过管道传输到Rx流的方式.
official angular2 documentation for HostListener没有提到这个目标:eventName语法,但this old dart documentation for 2.0.0-alpha.24确实提到了它.它似乎仍然适用于2.0.0-beta.12.
@Directive({ selector: '[draggable]' }) export class Draggable implements OnInit { mouseup = new EventEmitter<MouseEvent>(); mousedown = new EventEmitter<MouseEvent>(); mousemove = new EventEmitter<MouseEvent>(); mousedrag: Observable<{top,left}>; @HostListener('document:mouseup',['$event']) onMouseup(event: MouseEvent) { this.mouseup.emit(event); } @HostListener('mousedown',['$event']) onMousedown(event: MouseEvent) { this.mousedown.emit(event); return false; // Call preventDefault() on the event } @HostListener('document:mousemove',['$event']) onMousemove(event: MouseEvent) { this.mousemove.emit(event); } constructor(public element: ElementRef) { this.element.nativeElement.style.position = 'relative'; this.element.nativeElement.style.cursor = 'pointer'; this.mousedrag = this.mousedown.map(event => { return { top: event.clientY - this.element.nativeElement.getBoundingClientRect().top left: event.clientX - this.element.nativeElement.getBoundingClientRect().left,}; }) .flatMap( imageOffset => this.mousemove.map(pos => ({ top: pos.clientY - imageOffset.top,left: pos.clientX - imageOffset.left })) .takeUntil(this.mouseup) ); } ngOnInit() { this.mousedrag.subscribe({ next: pos => { this.element.nativeElement.style.top = pos.top + 'px'; this.element.nativeElement.style.left = pos.left + 'px'; } }); } }