2017-04-07 4 views
0

要素をドラッグしている間に、ページをゆっくりとスクロールさせるためにマウスを置くことができる要素を作成しようとしています。これは私のDrag-& -Dropエディタをサポートするために必要です。AngularJSのDragOverとDragLeave

ユーザーがアンカーの上にドラッグしてドラッグしているかどうかを検出しています。そうであれば、スロースクロールを開始する$intervalを開始します。マウスがアンカーを離れるか、ユーザーがドラッグを停止すると、スロースクロールはキャンセルされますが、スクロールはキャンセルされません。以下は私のコードです。

elem.on('dragover', mouseOver); 

elem.on('dragleave', mouseLeave); 
elem.on('dragend', mouseLeave); 

var scroller = null; 

function mouseOver(ev) { 
    ev.preventDefault(); 

    console.log('over'); 

    scroller = $interval(function() { 
     if (!scrolledToBottom()) { 
      $(window).scrollTop($(window).scrollTop() + 1); 
     } 
    }, 10); 

} 

function mouseLeave(ev) { 
    ev.preventDefault(); 

    console.log('left'); 

    $interval.cancel(scroller); 
    scroller = null; 
} 

function scrolledToBottom() { 
    return ($(window).scrollTop() + $(window).height()) == 
    $(document).height(); 
} 

console.logの火はうまくいますが、スクロール側は決してスクロールを停止しません。これはAngularがトリガされたときにAngularがイベントの内部を見ることができず、変更をスクロール側に適用できないためです。ただし、AngularにはngDragOverがありません.JQueryの実装についてのみ考えることができます。

提案がありますか?

+0

?要素をビューポートからドラッグすると、ウィンドウのスクロールが自動的に行われます。 – Gaurav

+0

コンピュータに精通している人にとっては賢明な言葉遣いですが、私のユーザはそうではないと思います。サイトに固定トップバーメニューがある場合は、これをスクロールしてバックアップすることもできません。 – FvB

+0

これは意味がありますが、あなたが紹介する他のアクセシビリティの問題があればそれを忘れないように注意してください。とにかく、私が投稿した答えを見てください。 – Gaurav

答えて

1

あなたのコードの問題は、あなたがたとえば、あなたのdragoverイベントハンドラがどのように見えるDuring the operations, several event types are fired and some event types might be fired many times (for example the drag and dragover event types).

こと elem.on('dragover', mouseOver)elem.on('dragleave', mouseLeave)elem.on('dragend', mouseLeave)様およびdoc mentionsなどのイベントを登録しているということです。だから、

function mouseOver(ev) { 
    ev.preventDefault(); 

    console.log('over'); 

    scroller = $interval(function() { 
     if (!scrolledToBottom()) { 
      $(window).scrollTop($(window).scrollTop() + 1); 
     } 
    }, 10); 

} 

、上記のイベントハンドラは複数回起動し、$intervalを複数回登録し、古い約束を緩和します。登録はまた、すぐにあなたが要素のドラッグを開始と呼ばれる場合

var scroller = null; 
function mouseOver(ev) { 
    ev.preventDefault(); 

    console.log('over'); 

    if (scroller === null) { // <-- This check will prevent multiple $interval registration. 
     scroller = $interval(function() { 
      if (!scrolledToBottom()) { 
       $(window).scrollTop($(window).scrollTop() + 1); 
      } 
     }, 10); 
    } 

} 

私はこのイベントハンドラとしてelem.on('dragleave', mouseLeave)イベントハンドラの登録呼び出しを削除します:

は、次のチェックを使用していることを修正してください。したがって、カスタムscollロジックをキャンセルします。

また、私は(これは単なるコード明確にするためである)のように、$intervalをキャンセルする前にチェックを作るためにあなたのdragendイベントハンドラを変更することを示唆している:ここで

function mouseLeave(ev) { 
    ev.preventDefault(); 

    if (scroller !== null) { // <-- Make a check before cancelling the 
     $interval.cancel(scroller); 
     scroller = null; 
    } 

} 

は試してみる作業例です。

あなたも、カスタムスクロールが必要な理由

angular.module('myApp', []) 
 
    .directive('drag', function($interval) { 
 
    return { 
 
     restrict: 'A', 
 
     link: function(scope, elem, attrs, ctrl) { 
 

 
     elem.on('dragover', mouseOver); 
 
     elem.on('dragend', mouseLeave); 
 

 
     var scroller = null; 
 

 
     function mouseOver(ev) { 
 
      ev.preventDefault(); 
 

 
      if (scroller === null) { 
 
      scroller = $interval(function() { 
 
       if (!scrolledToBottom()) { 
 
       $(window).scrollTop($(window).scrollTop() + 1); 
 
       } 
 
      }, 10); 
 
      } 
 

 
     } 
 

 
     function mouseLeave(ev) { 
 
      ev.preventDefault(); 
 

 
      if (scroller !== null) { 
 
      $interval.cancel(scroller); 
 
      scroller = null; 
 
      } 
 

 
     } 
 

 
     function scrolledToBottom() { 
 
      return ($(window).scrollTop() + $(window).height()) == 
 
      $(document).height(); 
 
     } 
 
     } 
 
    } 
 

 
    });
.container { 
 
    padding: 0; 
 
    margin: 0; 
 
    background: blue; 
 
    height: 800px; 
 
} 
 

 
.container .drag { 
 
    height: 300px; 
 
} 
 

 
.container .drag a { 
 
    color: white; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> 
 
<script src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js "></script> 
 

 
<div ng-app="myApp"> 
 

 
    <div class="container"> 
 
    
 
    <div class="drag"> 
 
     <a href="" drag>Drag Me</a> 
 
    </div> 
 

 
    </div> 
 

 
</div>

+0

パーフェクト!これは私が必要なすべてを持っています:) – FvB

関連する問題