2018年5月18日金曜日

マウスのチャタリングを確認する

 マウスが壊れてシングルクリックがダブルクリックになったり、ドラッグ中に離した判定になったりすることがあるじゃないですか。でも指が疲れているせいか本当に壊れいてるかはっきりなしないことがありますよね。


そこで Highcharts(グラフ)を使って可視化してみました。JavaScriptを使いマウスイベントをグラフに反映します。いつも通りやりかたは雑いです。
画像の赤い部分でマウス操作するとグラフに反映されます。
コードを少し変更すればクリックとダブルクリックが確認できます。

押してしばらくして離すを繰り返した結果が以下です。
[追記:ためしにブログ上においてみました]

 マウスダウン(押す)すると青の点が1になり、マウスアップ(離す)と黒の点が2になります。
上記の図だと離したときにチャタリングおこって意図していない結果になっています。

左ボタンを確認したら、


マウスのプロパティを左きき用にして右ボタンを確認してもいいでしょう。
(変更せずとも反応しますが、右クリックだとメニューが出るのでイベントを拾えているか不安…)
下記がコードです。htmlファイルとして保存してブラウザで表示すれば使えます。
外部のリソース(Highcharts)を使っているけどいいんかな?


ClickChart.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
<!DOCTYPE html>
<html lang = "ja">
  <head>
    <meta charset = "utf-8">
    <title>マウスチェック</title>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
     
<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>
<div id="text-button" onmousedown="fMouseDown(this)" onmouseup="fMouseUp(this)" style="background-color: red;"><p id="text">クリック</p></div>
  </head>
  <body>
   
<script>
var input_x0=Array(32);
var input_x1=Array(32);
var x0_rp = 0;
var x0_wp = 0;
var x1_rp = 0;
var x1_wp = 0;
 
document.getElementById("text-button").fMouseDown = function() {
    var x = (new Date()).getTime();
    input_x0[(x0_wp)] = x;
    x0_wp = (x0_wp +1)%32;
}
 
document.getElementById("text-button").fMouseUp = function() {
    var x = (new Date()).getTime();
    input_x1[(x1_wp)] = x;
    x1_wp = (x1_wp +1)%32;
}
 
/*
document.getElementById("text-button").onclick = function() {
    var x = (new Date()).getTime();
    input_x0[(x0_wp)] = x;
    x0_wp = (x0_wp +1)%32;
}
 
document.getElementById("text-button").ondblclick = function() {
    var x = (new Date()).getTime();
    input_x1[(x1_wp)] = x;
    x1_wp = (x1_wp +1)%32;
}
*/
 
Highcharts.setOptions({
  global: {
    useUTC: false
  },
    lang: {
        numericSymbols: null//軸のkキロ表示をやめる
    }
});
 
Highcharts.chart(&#039;container', {
  chart: {
   type: &#039;line',
    animation: Highcharts.svg, // don't animate in old IE
    marginRight: 100,//右の軸が隠れるので適切な値にする
    events: {
      load: function () {
        var series0 = this.series[0];
        var series1 = this.series[1];
 
        setInterval(function () {
        var x = (new Date()).getTime(); // current time
//series0に対する処理
        var p = x0_wp;
        while (x0_wp != x0_rp) {
         series0.addPoint([input_x0[x0_rp], 1], true, true);
         series0.addPoint([input_x0[x0_rp]+1, 0], true, true);
          
         series1.addPoint([input_x0[x0_rp], 0], true, true);
         series1.addPoint([input_x0[x0_rp]+1, 0], true, true);
         x0_rp = (x0_rp +1)%32;
        }
//series1に対する処理
        p = x1_wp;
        while (p != x1_rp) {
         series1.addPoint([input_x1[x1_rp], 2], true, true);
         series1.addPoint([input_x1[x1_rp]+1, 0], true, true);
          
         series0.addPoint([input_x0[x1_rp], 0], true, true);
         series0.addPoint([input_x0[x1_rp]+1, 0], true, true);
         x1_rp = (x1_rp +1)%32;
        }
       }, 500);//0.5秒のインターバルタイマ
      }
    }
     
  },
  title: {
    text: &#039;チャタリングチェック(赤い部分をクリックでチェック)'
  },
  plotOptions: {
        series: {
         marker: {
                enabledThreshold: 0//マークが見えるように
            }
        }
    },
  xAxis: {
    type: &#039;datetime',
    tickPixelInterval: 150
  },
  yAxis: [
      {
          title: {
              text: &#039;クリック'
          },
          plotLines: [{
              value: 0,
              width: 1,
              color: &#039;#FF8080'
          }],
          allowDecimals: false    //軸を整数表示
      },
  ],
  tooltip: {
    formatter: function () {
      return &#039;<b>' + this.series.name + '</b><br/>' +
        Highcharts.dateFormat(&#039;%Y-%m-%d %H:%M:%S', this.x) + '<br/>' + this.y;
    }
  },
  legend: {
    enabled: true    //凡例表示
  },
  exporting: {
    enabled: false
  },
   
  series: [{
    name: &#039;マウスダウン',
    yAxis: 0,
    data: (function () {
      var data = [],
        time = (new Date()).getTime(),
        i;
 
      for (i = -19; i <= 0; i += 1) {
        data.push({
          x: time + i * 500,
          y: 0
        });
      }
      return data;
    }())
  },
  {
    name: &#039;マウスアップ',
    yAxis: 0,
    data: (function () {
      var data = [],
        time = (new Date()).getTime(),
        i;
 
      for (i = -19; i <= 0; i += 1) {
        data.push({
          x: time + i * 500,
          y: 0
        });
      }
      return data;
    }())
   },
   ]
});
 
 
</script>
 
 
  </body>
</html>


注釈として、
マウスのイベントとタイマーのイベントが重なっても大丈夫なようにリングバッファでイベントの時間を格納しています。
イベントのタイミングでグラフに直接反映できればいいのですが、JavaScriptよくわからないのであきらめました。
23行目から33行目をコメントアウトして35行目から46行目を反映させればクリックとダブルクリックのイベントに変更できます。
70行目から88行目、ダウンもアップも同じ数が発生するようにしています。そうしないとX軸は全部のポイントを表示するようにしているためその対策です。
※アップとダウンはペアなので問題ないが、クリックとダブルクリックは困る。
またX軸の時間は可変なので時間がながい細かい部分がみづらくなります。対策はあきらめました。
101行目 値ありから0にすぐ戻しているため、デフォルト設定だとマークが近すぎでません。その対策で0を設定しています。
ちなみに今回は線ありでやっていますが、線の幅を0にするとマークだけになります。


ブログで直接実行もできるけどやめとこ。
マウスの調子が悪いので思いつきで作ってみました。明らかに壊れてるわ

0 件のコメント:

コメントを投稿