example else angular angular2-directives rxjs5

else - Cómo implementar un div arrastrable en Angular 2 usando Rx



ngif angular 6 example (4)

He estado tratando de hacer funcionar un div arrastrable usando Angular 2. Estoy usando este ejemplo del repositorio de angulo2-ejemplos como punto de partida, solo ajustando realmente el código para tener en cuenta la eliminación del método toRx() . El código funciona, pero no tiene en cuenta los eventos de mouseout . Esto significa que si hago clic en un div Draggable y muevo el mouse lentamente , el div se moverá con el mouse. Pero si muevo el mouse demasiado rápido, se envía un evento de mousemove lugar de un evento mousemove , y el arrastre se detiene.

¿Cómo puedo mantener el arrastre después de mover el mouse hasta el momento en que se mouseout un evento de mouseout ? He intentado fusionar el mouseout eventos mouseout con el mousemove , para que los eventos mouseout se traten como mousemove , pero eso no funciona.

Estoy usando 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 { }


Encontré la respuesta a esto en RxJs ¿Cómo lidiar con los eventos de documentos ? El quid del problema es que los eventos del mouse solo se envían a un elemento cuando el mouse está sobre ese elemento. Así que queremos que el evento de mousedown se limite a un elemento específico, pero tenemos que hacer un seguimiento de los mousemove globales de mousemove y mouseup . Aquí está el nuevo código. Note que el uso del decorador @HostListener en onMouseup y onMousemove especifica el objetivo como document:mouseup y document:mousemove . Así es como se canalizan los eventos globales en el flujo de Rx.

La documentación oficial de angular2 para HostListener no menciona este target:eventName sintaxis de target:eventName , pero esta documentación antigua de dart para 2.0.0-alpha.24 sí lo menciona. Parece que todavía funciona en 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''; } }); } }


Puedes usar esto: npm install ng2draggable

Use [ng2-draggable]="true" , no olvide el ="true"

Lo puedes encontrar aquí

https://github.com/cedvdb/ng2draggable

Aquí está el código:

@Directive({ selector: ''[ng2-draggable]'' }) export class Draggable implements OnInit{ topStart:number=0; leftStart:number=0; _allowDrag:boolean = true; md:boolean; constructor(public element: ElementRef) {} ngOnInit(){ // css changes if(this._allowDrag){ this.element.nativeElement.style.position = ''relative''; this.element.nativeElement.className += '' cursor-draggable''; } } @HostListener(''mousedown'', [''$event'']) onMouseDown(event:MouseEvent) { if(event.button === 2) return; // prevents right click drag, remove his if you don''t want it this.md = true; this.topStart = event.clientY - this.element.nativeElement.style.top.replace(''px'',''''); this.leftStart = event.clientX - this.element.nativeElement.style.left.replace(''px'',''''); } @HostListener(''document:mouseup'') onMouseUp(event:MouseEvent) { this.md = false; } @HostListener(''document:mousemove'', [''$event'']) onMouseMove(event:MouseEvent) { if(this.md && this._allowDrag){ this.element.nativeElement.style.top = (event.clientY - this.topStart) + ''px''; this.element.nativeElement.style.left = (event.clientX - this.leftStart) + ''px''; } } @HostListener(''touchstart'', [''$event'']) onTouchStart(event:TouchEvent) { this.md = true; this.topStart = event.changedTouches[0].clientY - this.element.nativeElement.style.top.replace(''px'',''''); this.leftStart = event.changedTouches[0].clientX - this.element.nativeElement.style.left.replace(''px'',''''); event.stopPropagation(); } @HostListener(''document:touchend'') onTouchEnd() { this.md = false; } @HostListener(''document:touchmove'', [''$event'']) onTouchMove(event:TouchEvent) { if(this.md && this._allowDrag){ this.element.nativeElement.style.top = ( event.changedTouches[0].clientY - this.topStart ) + ''px''; this.element.nativeElement.style.left = ( event.changedTouches[0].clientX - this.leftStart ) + ''px''; } event.stopPropagation(); } @Input(''ng2-draggable'') set allowDrag(value:boolean){ this._allowDrag = value; if(this._allowDrag) this.element.nativeElement.className += '' cursor-draggable''; else this.element.nativeElement.className = this.element.nativeElement.className .replace('' cursor-draggable'',''''); } }


Tengo el mismo problema con la ventana emergente que se puede arrastrar, así que agrego los eventos mousemove y mouseup al documento en mousedown y los elimino en mouseup. Utilizo la respuesta de Eric Martínez para agregar y eliminar dinámicamente el detector de eventos.

Modelo:

<div class="popup-win" (mousedown)="mousedown($event)"></div>

Componente:

constructor(private elementRef: ElementRef, private renderer: Renderer2) {} mousedown(event: any) { this.xStartElementPoint = this.curX; this.yStartElementPoint = this.curY; this.xStartMousePoint = event.pageX; this.yStartMousePoint = event.pageY; this.mousemoveEvent = this.renderer.listen("document", "mousemove", this.dragging); this.mouseupEvent = this.renderer.listen("document", "mouseup", this.mouseup); } dragging(event: any) { this.curX = this.xStartElementPoint + (event.pageX - this.xStartMousePoint); this.curY = this.yStartElementPoint + (event.pageY - this.yStartMousePoint); } mouseup(event: any) { // Remove listeners this.mousemoveEvent(); this.mouseupEvent(); }

Aquí hay un ejemplo ejecutable en Plunker .


Usted podría crear una gran división que cubre la pantalla de bienes raíces. Para empezar, este div tiene un índice z más bajo que el div que desea arrastrar. Al recibir mousedown, cambia el índice z del div para que sea más alto que el elemento de arrastre y recibe eventos de movimiento del mouse en este div. Puede usar n para calcular la posición del elemento de arrastre. Luego puede detener y enviar el div de nuevo cuando reciba un mouse arriba.

Recientemente he escrito un marco modular de arrastrar y soltar en Angular2. Por favor, pruébalo y proporciona comentarios.

https://github.com/ivegotwings/ng2Draggable

Sin embargo, detengo el arrastre una vez que se desencadena el evento mouseout.