So implementieren Sie ein ziehbares Div in Angular 2 mit Rx


Chris

Ich habe versucht, ein ziehbares Div mit Angular 2 zum Laufen zu bringen. Ich verwende dieses Beispiel aus dem Angular2-Beispiel-Repo als Ausgangspunkt und passe den Code nur wirklich an, um das Entfernen der toRx()Methode zu berücksichtigen . Der Code funktioniert, berücksichtigt jedoch keine mouseoutEreignisse. Das heißt, wenn ich auf ein ziehbares Div klicke und die Maus langsam bewege, bewegt sich das Div mit der Maus. Wenn ich die Maus jedoch zu schnell bewege, mouseoutwird anstelle eines mousemoveEreignisses ein Ereignis gesendet , und das Ziehen wird gestoppt.

Wie kann ich das Ziehen fortsetzen, nachdem die Maus so weit bewegt wurde, dass ein mouseoutEreignis ausgelöst wird? Ich habe versucht, den mouseoutEreignisstrom mit dem mousemoveeinen zusammenzuführen, damit mouseoutEreignisse wie mousemovesolche behandelt werden, aber das funktioniert nicht.

Ich verwende 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 {
}
Chris

Ich fand die Antwort auf diese Frage in RxJs Wie mit Dokumentereignissen viel tun . Der Kern des Problems besteht darin, dass Mausereignisse nur an ein Element gesendet werden, wenn sich die Maus über diesem Element befindet. Wir möchten also, dass das mousedownEreignis auf ein bestimmtes Element beschränkt ist, aber wir müssen globale Ereignisse mousemoveund mouseupEreignisse verfolgen . Hier ist der neue Code. Beachten Sie die Verwendung des @HostListenerDekorators an onMouseupund geben Sie onMousemovedas Ziel als document:mouseupund an document:mousemove. Auf diese Weise werden die globalen Ereignisse in den Rx-Stream geleitet.

In der offiziellen Angular2-Dokumentation für HostListener wird diese target:eventNameSyntax nicht erwähnt , in dieser alten Dart-Dokumentation für 2.0.0-alpha.24 wird sie jedoch erwähnt. Es scheint immer noch in 2.0.0-beta.12 zu funktionieren.

@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';
            }
        });
    }
}

Verwandte Artikel


Zentrieren Sie ein festes ziehbares Div

Jessica Ich habe eine feste, div die ich versuche, vertikal und horizontal zu zentrieren. Ja, ich weiß, dass es viele Fragen und Tutorials gibt, um dies durchzuführen. Ich überprüfte und befolgte die Anweisungen. Hier ist eine, die ich implementiert habe: #dra

So fügen Sie ein ziehbares Symbol mit der Navigationsleiste hinzu

Ranjith Kumar Mein Problem: Ich möchte ein ziehbares Symbol in die Navigationsschublade einfügen. Dieses Symbol wird mit der Listenansicht der Navigationsschublade beim Öffnen der Schublade kombiniert. ähnlich sehen, Was ich versucht habe, Ich suchte in StackO

So erstellen Sie ein ziehbares Element mit HammerJs und Angular

Arthur Decker Ich versuche, eine ziehbare Funktionalität mit HammerJs und Angular zu implementieren, aber mein Element bewegt sich nicht. Die Mauspunkte werden ausgedruckt, aber das Element bewegt sich nicht. @Component({ selector: 'app-example', styles: [

So zeichnen Sie ein ziehbares Polygon

Philipp In Bezug auf dieses Matplotlib-Beispiel, das ziehbare Rechtecke zeichnet, habe ich versucht, dasselbe mit Polygonen zu tun. Bisher kann ich ein Polygon zeichnen und irgendwo auf die Leinwand ziehen. Wenn ich die Maustaste loslasse, kann ich das Polygon

So erstellen Sie ein ziehbares Plotobjekt

Tropfen Ich habe ein grafisches Histogramm mit einer Form im Hintergrund. Wie kann ich das Hintergrundobjekt rechts / links ziehbar machen? import numpy as np import plotly.graph_objects as go # generate data data = np.random.normal(0,10,500) # plot histogra

So implementieren Sie eine konfigurierbare Tabelle mit Angular 2+

Mark Chidlow Ich versuche, eine Tabelle basierend auf einer JSON-Konfiguration zu generieren. Obwohl ich die Tabellenüberschriften OK erstellen kann, weiß ich nicht, wie ich die Zeilenzellendaten nach Feldnamen dynamisch auswählen kann. Das habe ich: columns =

So erstellen Sie ein ziehbares Div mit Clipping

Thomas Ich versuche ein Browserspiel zu bauen und meine Spielkarte ist auf Quadraten mit Hintergrund aufgebaut. Das umgebende Layout ist einfach mit <header>, <footer>, <main>und <aside>während die Größe von <main>dynamisch abhängig von der Bildschirmgröße ist