2017-07-14 13 views
1

私はこの作業をしていますPlunker例、マウスをドラッグしてカードを選択することができます。 IMG#でカード - 私の問題は、コードがバグの多くを持っていると私は私が(img1img2を修正したいこれに類似 何かDemoコンポーネントのAngular 4で、より優れたMouseEvent実装を行うにはどうすればよいですか?

ここで何かをしたいということです

2を前にクリックしたとき)、別のことは、マウスを速くドラッグするとカードが選択されないことがあることです。

は、ここに私のコンポーネントのコードの読み取りのための

export class App { 

    private dragStart:number = 0; 
    private dragOver:number = 0; 
    public users:Array<{id?: number; name: string; admin: boolean;}> = [ 
     { name: 'Alexis Wursten', admin: false }, 
     { name: 'Janco Boscan', admin: true }, 
     { name: 'Noemi Iturralde', admin: false }, 
    ]; 
    public added: string[] = []; 
    x1 = 0; y1 = 0; x2 = 0; y2 = 0; 

    @ViewChild('selector') selector: ElementRef; 

    constructor(private renderer: Renderer2) { 
    } 

    isRectangeVisible = false; 
    isMouseDown = false; 

    @HostListener('mousedown', ['$event']) 
    onMouseDown(ev) { 
    this.dragStart = ev.clientY; 
    this.isMouseDown = true; 

    } 

    @HostListener('document:mouseup', ['$event']) 
    onMouseUp(ev) { 
    this.dragStart = 0; 
    this.dragOver = 0; 
    this.renderer.setStyle(this.selector.nativeElement, 'display', 'none'); 
    this.isRectangeVisible = false; 
    this.isMouseDown = false; 
    } 

    @HostListener('document:mousemove', ['$event']) 
    onMouseMove(ev) { 

    if(!this.isRectangeVisible && this.isMouseDown){ 
     this.renderer.setStyle(this.selector.nativeElement, 'display', 'block'); 
     this.x1 = ev.clientX; 
     this.y1 = ev.clientY; 
     this.isRectangeVisible = true; 
    } 

    this.x2 = ev.clientX; 
    this.y2 = ev.clientY; 
    this.reCalc(); 
    } 

    reCalc() { 
    const x3 = Math.min(this.x1, this.x2); 
    const x4 = Math.max(this.x1, this.x2); 
    const y3 = Math.min(this.y1, this.y2); 
    const y4 = Math.max(this.y1, this.y2); 
    this.renderer.setStyle(this.selector.nativeElement, 'left', x3 + 'px'); 
    this.renderer.setStyle(this.selector.nativeElement, 'top', y3 + 'px'); 
    this.renderer.setStyle(this.selector.nativeElement, 'width', x4 - x3 + 'px'); 
    this.renderer.setStyle(this.selector.nativeElement, 'height', y4 - y3 + 'px'); 
    } 

    onSelecUser(item) { 
     if(this.added.indexOf(item.name)===-1) { // or compare by id 
      this.added = this.added.concat([item.name]); 
     } 
     else { 
      this.added = this.added.filter((x) => item.name!==x); // or compare by id 
     } 

     item.selected = !item.selected ? true : false; 
    } 

    onMouseOver(ev, item) { 
     if(ev.which!==1) { 
      return false; 
     } 

     ev.preventDefault(); 

     if(ev.type==='mouseenter' && !item.selected) { 
      this.dragOver = ev.clientY - this.dragStart > 0 ? 1:-1; 
      this.onSelecUser(item); 
      return false; 
     } 

     if(ev.type==='mouseleave') { 
      if(this.dragOver===1 && ev.clientY < ev.target.offsetTop && item.selected) { 
       console.log('desel...', item); 
       this.onSelecUser(item); 
       return false; 
      } 
      if(this.dragOver===-1 && ev.clientY > ev.target.offsetTop && item.selected) { 
       console.log('desel...', item); 
       this.onSelecUser(item); 
       return false; 
      } 
     } 
    } 
} 

おかげです。

答えて

2

UPDATE#1: https://plnkr.co/edit/d9aTb0E0OKFfTSIAM0MY?p=preview

追加オプション/選択するには、クリックして、ユーザーの選択を解除します。
そのため、リセットコードは必要ありません。

@HostListener('mousedown', ['$event']) 
    onMouseDown(ev) { 
    this.dragStart = ev.clientY; 
    this.isMouseDown = true; 
    } 

divのクリックハンドラのみが変更されました。

(click)="onSelecPersona(user, !user.selected)" 

INITIAL ANSWER:ここ がコードに変更されます。

(1)HTMLの選択: "ユーザーの選択" CSS https://plnkr.co/edit/QryFWtLQwNuGkrtzDehm?p=preview

それはいくつかの問題を解決します選択が「行」境界から始まるので、「カード」の「行」の上になければならない。

.row { 
    user-select: none; 
    -moz-user-select: none; 
} 
.card-content { 
    padding: 0; 
} 

(2)選択されたdivの処理:初期実装では、ユーザーのdivのマウスイベントが使用されます。これは、「セレクタ」矩形が「ユーザ」divの境界を横切ることはない(つまり、選択境界内にいるが、選択境界内にある)場合は処理しない。 私の実装では、 "selector"と "user" divの重なりを計算して、ユーザーが選択したかどうかを判断します。

 <div class="card" 
      #ucard 
      [attr.id]="user.name" 
      [class.selected]="user.selected" 
      *ngFor="let user of users" 
      (click)="onSelecPersona(user, !user.selected)" 
     > 

    import {Component, NgModule, HostListener, Renderer2, ElementRef, ViewChild, ViewChildren } from '@angular/core' 
    ... 
    @ViewChildren('ucard') components: QueryList<ElementRef>; 
    ... 
     // return true if two HTML elements overlap 
     overlap(e1:ElementRef, e2:ElementRef){ 
     var rect1 = e1.getBoundingClientRect(); 
     var rect2 = e2.getBoundingClientRect(); 

     return !(
      rect1.top > rect2.bottom || 
      rect1.right < rect2.left || 
      rect1.bottom < rect2.top || 
      rect1.left > rect2.right 
     ); 
     } 

     // updates user selection based on the current "selector" 
     markSelected(){ 
     this.components.forEach(it=> { 
      var overlaps: boolean = this.overlap(this.selector.nativeElement, it.nativeElement); 
      this.onSelecPersona(this.users.find(u=> u.name == it.nativeElement.id), overlaps); 
     }); 
     } 
+0

ありがとうございます、私を大いに助けてくれました。私はまだノーベルであり、上級者から何かを知ることは素晴らしいことです。 通常のクリックでカードを選択するにはどうすればいいですか?それと完璧になるでしょう。 –

+0

デモのようなものは、カード以外のカードの選択を解除し、矩形と通常のクリックで選択します。 –

+1

は、ユーザーを選択/選択解除するためのオプションを追加した新しいプランカのリンクで、私の答えを更新しました。 – mtim

関連する問題