0

眠気の夜の後、私はこの質問について、少なくとも私にとっては根本的に頭がおかしいと思う何かを発見しました.

上記の私のコードのように、マウスの座標は正確ではありません(移動が発生したときにキャンバス全体を再作成する必要がある高速処理であると思います)。このコードを少しずつテストしたところ、問題はループにあるのではなく、精度にあることがわかりました。

if ((newMouseX !== mouseX) && (newMouseY !== mouseY)).

コードのこの部分をより遅い時間でテストした場合 (「停止」したときに目が座標の違いを検出できるようになりますnewMouseX) mouseX9% の確率で、約 1% の確率でしかありません (統計は測定していませんが、数回のテストで選んだものです)。

私はそれをフィドルで動作させることはできませんが、それをテスト場にコピーして、私の意味を確認できると思います. フィドルで動作させることができれば素晴らしいので、専門家はそれを短くすることができます:)

これは、マウスが「停止」する必要がある場合でも、コードによって「動いている」と見なされ、その間に数回「停止」するため、ループを1秒間に何度も呼び出すことを意味します。これが問題です持っています。

これをテストし、統計的な精度/アドバイスを思いつくことができる人を含む、他の専門家からのコメントを喜んで聞きます.

私のアドバイスと当面の解決策は、いずれかの座標の差が 10 ピクセルを超える場合の動きを考慮することです。もちろん、これには問題がありますが、より良い解決策が見つかるまで、そのままにしておくことができます。

だから代わりに

if ((newMouseX !== mouseX) && (newMouseY !== mouseY))

利用した

if (( Math.abs(newMouseX - mouseX) > 10) || ( Math.abs(newMouseY != mouseY) > 10) )

考慮すべきもう1つのことは、マウスの位置がターゲットキャンバス領域から外れるときの対処方法です...現時点では無限の動きのように見えます!

質問:

mouseX&を比較できるように、正確なマウス座標を取得するにはどうすればよいnewMouseXですか?

ありがとう。

4

2 に答える 2

2

マウスの精度はハードウェアによって決まります。たとえば、高精度のマウスは、組み込みのマウス パッドとは異なる結果を生成します (タッチ デバイスは言うまでもありません)。

ただし、これはコードとシナリオの問題ではありません。mousemoveイベントを聞いているだけです。定義上、マウスを動かしたときにのみイベントがスローされます。したがって、新しいマウスの位置が前の位置と同じになることはありません。それは不可能であり、100% オフにする必要があります (チェックする前に最後が握りこぶしの位置に戻る 2 つ以上の動きをトリガーしている場合を除きます)。

mousedown通常は、およびイベントをリッスンし、マウスの動きmouseupに依存せずにトリガーします。マウスの動きのみに基づいて開始と停止を検出することは、あらゆる状況下で不可能と見なされます。

妥協して、開始とは何か、停止とは何かを定義することができます。マウスが x ミリ秒経過しても動かない場合は、停止したと見なされます (開始は最初の移動になります)。

これは、ストップを検出する必要があるたびに、このルールに従う必要があることを意味します。絵を描いているところをイメージすると、時にはゆっくりと、時には速く描くことができます。または、何も描画せずにマウスを新しい位置に移動するにはどうすればよいですか...マウスボタンが発明されるのには十分な理由があります:-)

ルールはすぐに役に立たないことが判明します (または、過度に複雑で複数のエラーが発生する傾向があります)。

キャンバス外のマウスの位置については、これを処理する方法がいくつかあります。

以下を呼び出して、キャンバスの境界を取得できます。

var canvasRect = canvas.getBoundingClientRect();

これにより、マウスの位置がこの長方形の内側または外側にあるときにチェックするプロパティが提供されます。

もう 1 つの方法は、canvas 要素のmouseleaveおよびmouseenterイベントをリッスンすることです。

3 つ目は、実際にマウス ボタンを使用することです。キャンバス要素でマウス ボタンを押したままにすると、mousemoveイベントが考慮されるようにフラグが設定されます。

これは、マウス ボタンが離されるまでリッスンし続けます。キャンバスの外で解放し、キャンバスmouseupイベントを使用している場合、検出されません。そのため、どちらの場合でもトリガーされるwindowのイベントをリッスンする必要があります。mouseup

これはmousemoveイベントにも当てはまります。window イベントを使用すると、キャンバス外の位置を記録できます。これをしたくない場合はmousemove、キャンバスの境界でクリップするキャンバスを使用できます。

要約すると、次のようになります。

mousedownmousemoveとイベントを組み合わせて使用mouseup​​すると問題ありません。これらのすべてのイベントは、マウスの位置に対して配信clientXされます。clientY

よろしければ、私のeasyCanvas プロジェクトに移動してサンプルを実行してテストすることもできます:
サンプル - マウス イベントの詳細

これにより、マウスのダウン、移動、およびアップの詳細が表示されます (詳細は他の情報で拡張されますが、少なくともマウスの位置を確認できます。移動せずにクリックすると、マウスの位置がまったく同じであることがわかります)。

于 2013-07-16T14:39:16.797 に答える
-1

http://jsfiddle.net/6czap/74/

私はこれを助けたことを願っています:)

$("div").mousemove(function(e){
   var pageCoords = "( " + e.pageX + ", " + e.pageY + " )";
  var clientCoords = "( " + e.clientX + ", " + e.clientY + " )";
  $("span:first").text("( e.pageX, e.pageY ) : " + pageCoords);
  $("span:last").text("( e.clientX, e.clientY ) : " + clientCoords);
});
于 2013-07-16T14:01:02.050 に答える