1

Opera Mobile 12を実行しているAndroidタブレットで実行される Javascript が少しあります。タブレットはオフィスの壁に取り付けられているため、このオフィスで働くすべての人が計時システムとして使用します (つまり、出勤/退勤に使用します)。この JavaScript は、特定のイベントが発生したときにユーザーの写真を撮り、この写真をデータ URL に変換して、サーバーに送信できるようにします。ただし、これはすべてバックグラウンドで実行されます。 要素要素は両方とも に設定されます。videocanvasdisplay:none;

Web カメラの相互作用を処理するコードは次のとおりです。

var Webcam = function() {
  var video = document.getElementById('video');
  var stream_webcam = function(stream) {
    video.addEventListener('loadedmetadata', function(){
      video.play();
    }, false);
    video.src = window.URL.createObjectURL(stream);
  }

  // start recording
  if (navigator.getUserMedia)
    navigator.getUserMedia({video: true}, stream_webcam);
  else
    _error("No navigator.getUserMedia support detected!");

  var w = {};

  w.snap = function(callback) {
    var canvas = document.getElementById('canvas');
    canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
    // delay is incurred in writing to canvas on opera mobile
    setTimeout(function() {
      callback(canvas.toDataURL());
    }, 1);
  };

  return w;
}

w.snap(callback)ユーザーが特定のボタンを押すと呼び出されます。問題は、への呼び出しと、実際にキャンバスに描画される画像との間にかなりの遅延があることです。発生する問題は次のとおりです。drawImage

  • ユーザー 1 はタブレットを使用し、ボタンを押して、写真を「スナップ」し、サーバーに送信します。サーバーは、空の透明なイメージを受け取ります。( html5 キャンバス toDataURL が空白の画像を返すのと同じ問題ではありません。最初の画像は空白であるため、サーバーに送信されるデータは大幅に少なくなります)
  • 数分後、ユーザー 2 がタブレットを使用してボタンを押すと、写真が「スナップ」されます。サーバーはユーザー 1 の写真を受け取ります。
  • その後、ユーザー 3 が同じことを行い、サーバーはユーザー 2 の写真を取得します。

だから私は への呼び出しtoDataURL()が古いデータを返していると推測drawImage()しています。(非同期であるとどこかで読みましたが、確認できず、描画が終了したときにイベントをアタッチする方法が見つかりません。)

私はもう試した:

  • タイムアウトをsnap()さまざまな値に変更します。私が試した最高は2000でしたが、同じ問題が発生しました。(誰かがもっと高い数字を提案してくれたら、喜んで試してみますが、あまり高くしたくありません。なぜなら、あまり高くすると、ユーザー 2 を処理する前にユーザー 3 の写真が撮られる可能性があるからです。写真、つまり、完全に失う可能性があります!)
  • ページが最初に読み込まれたときにキャンバスに何かを描画させましたが、それは修正されませんでした.ユーザー1が写真を撮られたとき、サーバーはユーザー1の写真ではなく、ページが読み込まれたときに撮影された写真を受け取りました.
  • getElementByIdを呼び出す前に、を使用してキャンバス要素を再度「取得」しますtoDataURL

さらにいくつかのメモ:

  • これは、Chrome と Opera の私のコンピューター (MacBook Air) で正常に動作します。
  • デバッガーを使用して確実に複製することはできません (Opera Dragonfly を使用してタブレットにリンクします)。
  • 私の知る限り、Opera Mobile は、写真をサポートしgetUserMedia、写真を撮ることができる唯一の Android ブラウザーです。
  • display:none;とからを削除するvideocanvas、(タブレット上で) 正しく動作します。この問題は、ビデオとキャンバスが設定されている場合にのみ発生します。display:none;

このページはスクロールやズームを必要としないシングル ページ アプリであるため、考えられる回避策は、ビデオとキャンバスをページ フォールドの下に移動し、JavaScript でスクロールを無効にすることです (つまり、ユーザーがスクロールするたびに上部にスクロールします)。

しかし、可能であれば、回避策よりも適切な修正を希望します!

4

2 に答える 2

4

あまり良い解決策はありませんが、非表示に設定して、dom を介して非表示のキャンバスを処理しないことをお勧めします。

それ以外の

 var canvas = document.getElementById('canvas');

試す

var canvas = document.createElement('canvas');
 canvas.width = video.width;
 canvas.height = video.height;
 canvas.getContext('2d').drawImage(video, 0, 0)

このようにして、DOM から分離されます。

また、なぜ使用しないのですか

canvas.toDataURL("image/jpg")?

編集: また、それを設計している場合、他のブラウザーを試しましたか? 利用可能な他のブラウザや phonegap を使用するよりも、Opera に制限されているのは何ですか?

編集 2: 考えてみると、Canvas には、写真を 2 つに分けて配置するためのオプションが他に 2 つあります。それらの2つは次のとおりです。

var imgData = canvas.getContext('2d').getImageData(0,0,canvas.width,canvas.height);

-また-

canvas.getContext('2d').putImageData(imgData,0,0);

これら 2 つは、コンテキストに対して行ったスケーリングを無視しますが、はるかに直接的で、多くの場合高速であることがわかりました。これらは toDataURL と drawImage の確実な代替手段ですが、これらから入れたり取得したりする画像データは、次の形式の配列としてエンコードされます。

[r1、b1、g1、a1、r2、b2、g2、a2....]

それらのドキュメントは次の場所にあります。

http://www.w3schools.com/tags/canvas_putimagedata.asp http://www.w3schools.com/tags/canvas_getimagedata.asp

于 2013-02-23T10:45:19.647 に答える
2

Android の一部のバージョンで問題が発生してtoDataUrl();います。

http://code.google.com/p/todataurl-png-js/wiki/FirstSteps

スクリプト: http://todataurl-png-js.googlecode.com/svn/trunk/todataurl.js

これをあなたのに貼り付けますhead

<script src="todataurl.js"></script>
于 2013-05-09T15:08:52.997 に答える