2016-03-17 12 views
9

मेरा उपयोगकर्ता किसी ऑब्जेक्ट को कैनवास में माउस द्वारा स्थानांतरित करने (या घुमाने) करने में सक्षम होना चाहिए। जब माउस घटनाएं होती हैं तो स्क्रीन समन्वय का उपयोग अंतिम घटना में डेल्टा (दिशा और लंबाई) की गणना करने के लिए किया जाता है। कुछ भी नहीं विशेष ...कोणीय 2: माउस इवेंट हैंडलिंग (वर्तमान स्थिति से संबंधित आंदोलन)

  1. mousedown (प्रथम समन्वय मिलता है)
  2. MouseMove (n वें समन्वय हो, deltaXY गणना, deltaXY द्वारा वस्तु को स्थानांतरित)
  3. mouseup (चरण 2 के रूप में ही है और MouseMove और mouseup रोक घटना हैंडलिंग)

घटनाओं की इस श्रृंखला के बाद एक ही कार्रवाई को दोहराना संभव होना चाहिए।

यह पुराना उदाहरण toRx कॉल को हटाने के बाद अपेक्षित कार्य करता है। लेकिन यहाँ पहली समन्वय करने के लिए डेल्टा निर्धारित होता है:

@Component({ 
    selector: 'home', 
    providers: [Scene], 
    template: '<canvas #canvas id="3dview"></canvas>' 
}) 
export class Home { 
    @ViewChild('canvas') canvas: ElementRef; 
    private scene: Scene; 
    private mousedrag = new EventEmitter(); 
    private mouseup = new EventEmitter<MouseEvent>(); 
    private mousedown = new EventEmitter<MouseEvent>(); 
    private mousemove = new EventEmitter<MouseEvent>(); 
    private last: MouseEvent; 
    private el: HTMLElement; 

    @HostListener('mouseup', ['$event']) 
    onMouseup(event: MouseEvent) { this.mouseup.emit(event); } 

    @HostListener('mousemove', ['$event']) 
    onMousemove(event: MouseEvent) { this.mousemove.emit(event); } 

    constructor(@Inject(ElementRef) elementRef: ElementRef, scene: Scene) { 
    this.el = elementRef.nativeElement; 
    this.scene = scene; 
    } 

    @HostListener('mousedown', ['$event']) 
    mouseHandling(event) { 
    event.preventDefault(); 
    console.log('mousedown', event); 
    this.last = event; 
    this.mousemove.subscribe({next: evt => { 
     console.log('mousemove.subscribe', evt); 
     this.mousedrag.emit(evt); 
    }}); 
    this.mouseup.subscribe({next: evt => { 
     console.log('mousemove.subscribe', evt); 
     this.mousedrag.emit(evt); 
     this.mousemove.unsubscribe(); 
     this.mouseup.unsubscribe(); 
    }}); 
    } 

    ngOnInit() { 
    console.log('init'); 
    this.mousedrag.subscribe({ 
     next: evt => { 
     console.log('mousedrag.subscribe', evt); 
     this.scene.rotate(
      evt.clientX - this.last.clientX, 
      evt.clientY - this.last.clientY); 
     this.last = evt; 
     } 
    }); 
    } 
    ... 
} 

यह केवल एक चक्र के लिए काम करता है: github.com:rx-draggable

यहाँ उदाहरण से कोड अनुकूल करने के लिए मेरे प्रयास है।

Uncaught EXCEPTION: Error during evaluation of "mousemove"

ORIGINAL EXCEPTION: ObjectUnsubscribedError

ERROR CONTEXT: EventEvaluationErrorContext

mousemove सदस्यता को रद्द करने से काम नहीं करता: mouseup घटना के बाद मैं यह त्रुटि हुई। त्रुटि निम्नलिखित सभी mousemoves के लिए दोहराना है।

क्या आपको पता है कि मेरे कोड में क्या गलत है? क्या इस समस्या को हल करने के लिए एक अलग सुरुचिपूर्ण दृष्टिकोण है?

उत्तर

15

मुझे विश्वास है कि आपकी समस्या unsubscribe() और remove(sub : Subscription) के बीच EventEmitter पर अंतर के साथ बताती है। लेकिन सदस्यता के उपयोग के बिना इसे करना संभव है (@HostListener द्वारा बनाए गए लोगों को छोड़कर) और इसे पढ़ने में आसान बनाते हैं। मैंने आपके कोड को थोड़ा सा लिखा है। document या window पर अपना mouseupevent डालने पर विचार कर सकते हैं, अन्यथा यदि आप अपने माउस को कैनवास के बाहर छोड़ देते हैं तो आपको अजीब व्यवहार मिलता है।

चेतावनी: अपरीक्षित कोड आगे

@Component({ 
    selector: 'home', 
    providers: [Scene], 
    template: '<canvas #canvas id="3dview"></canvas>' 
}) 
export class Home { 
    @ViewChild('canvas') 
    canvas: ElementRef; 

    private scene: Scene; 
    private last: MouseEvent; 
    private el: HTMLElement; 

    private mouseDown : boolean = false; 

    @HostListener('mouseup') 
    onMouseup() { 
     this.mouseDown = false; 
    } 

    @HostListener('mousemove', ['$event']) 
    onMousemove(event: MouseEvent) { 
     if(this.mouseDown) { 
      this.scene.rotate(
       event.clientX - this.last.clientX, 
       event.clientY - this.last.clientY 
      ); 
      this.last = event; 
     } 
    } 

    @HostListener('mousedown', ['$event']) 
    onMousedown(event) { 
     this.mouseDown = true; 
     this.last = event; 
    } 

    constructor(elementRef: ElementRef, scene: Scene) { 
     this.el = elementRef.nativeElement; 
     this.scene = scene; 
    } 
} 
+0

धन्यवाद अच्छा काम करता है:

यहाँ एक उदाहरण है। –

+0

आपका पुराना कोड, जो 'निकालने' का उपयोग करता है, काम नहीं करता है, आपको कोई विचार है क्यों? क्या आप एंगुलर 2 के साथ प्रतिक्रियाशील सामान सीखने के लिए एक अच्छा संसाधन जानते हैं? –

+0

@ मीको एमएम, मैंने 'निकालने' का परीक्षण नहीं किया, लेकिन मैंने इसे इस तरह से पहले इस्तेमाल किया और यह काम किया। मेरे पास कोई अच्छा संसाधन नहीं है, और मैं खेलते समय सीख रहा हूं :)। स्वीकार करने के लिए धन्यवाद। खुशी है कि मैं – PierreDuc

3

समस्या यह है कि आप उस कोड प्रतिक्रियाशील नहीं है है। प्रतिक्रियाशील प्रोग्रामिंग में सभी व्यवहार सजावट समय पर परिभाषित किए जाने चाहिए और केवल एक सदस्यता की आवश्यकता है। , Angular2/rxjs mouse translation/rotation

import {Component, NgModule, OnInit, ViewChild} from '@angular/core' 
import {BrowserModule, ElementRef, MouseEvent} from '@angular/platform-browser' 
import {Observable} from 'rxjs/Observable'; 
import 'rxjs/add/observable/fromEvent'; 
import 'rxjs/add/operator/map'; 
import 'rxjs/add/operator/switchMapTo'; 
import 'rxjs/add/operator/takeUntil'; 
import 'rxjs/add/operator/combineLatest'; 
import 'rxjs/add/operator/startWith'; 

@Component({ 
    selector: 'my-app', 
    styles: [` 
    canvas{ 
    border: 1px solid red; 
    }`], 
    template: ` 
    <div> 
     <h2>translate/Rotate by mouse</h2> 
     <canvas #canvas id="3dview"></canvas> 
     <p>Translate by delta: {{relativeTo$|async|json}}</p> 
     <p>Rotate by angle: {{rotateToAngle$|async|json}}</p> 
    </div> 
    ` 
}) 
export class App extends OnInit { 

    @ViewChild('canvas') 
    canvas: ElementRef; 

    relativeTo$: Observable<{dx:number, dy:number, start: MouseEvent}>; 
    rotateToAngle$: Observable<{angle:number, start: MouseEvent}>; 

    ngOnInit() { 
     const canvasNE = this.canvas.nativeElement; 

     const mouseDown$ = Observable.fromEvent(canvasNE, 'mousedown'); 
     const mouseMove$ = Observable.fromEvent(canvasNE, 'mousemove'); 
     const mouseUp$ = Observable.fromEvent(canvasNE, 'mouseup'); 

     const moveUntilMouseUp$= mouseMove$.takeUntil(mouseUp$); 
     const startRotate$ = mouseDown$.switchMapTo(moveUntilMouseUp$.startWith(null)); 

     const relativePoint = (start: MouseEvent, end: MouseEvent): {x:number, y:number} => 
     (start && end && { 
     dx: start.clientX - end.clientX, 
     dy: start.clientY - end.clientY, 
     start: start 
     } || {}); 

     this.relativeTo$ = startRotate$ 
     .combineLatest(mouseDown$) 
     .map(arr => relativePoint(arr[0],arr[1])); 

     this.rotateToAngle$ = this.relativeTo$ 
     .map((tr) => ({angle: Math.atan2(tr.dy, tr.dx), start: tr.start})); 

//  this.relativeTo$.subscribe(console.log.bind(console,'rotate:')); 
//  this.rotateToAngle$.subscribe(console.log.bind(console,'rotate 0:')); 
    } 
} 

@NgModule({ 
    imports: [ BrowserModule ], 
    declarations: [ App ], 
    bootstrap: [ App ] 
}) 
export class AppModule {} 
संबंधित मुद्दे