上下文drawImage / canvas toDataURL在opera手机上显着滞后 [英] context drawImage / canvas toDataURL lagging significantly on opera mobile

查看:428
本文介绍了上下文drawImage / canvas toDataURL在opera手机上显着滞后的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个运行 Android 平板电脑,运行 Opera Mobile 12 的Javascript。平板电脑连接到办公室的墙上,所以在这个办公室工作的每个人都使用平板电脑作为计时系统(即,他们使用计时系统或工作时钟)。此javascript会在特定事件发生时拍摄用户的照片,然后将此照片转换为数据网址,以便将其发送到服务器。这一切都在后台运行,但视频 canvas 元素都设置为 display:none;



b

  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);
}

//开始录制
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);
//在opera mobile上写canvas的时候会发生延迟
setTimeout(function(){
callback(canvas.toDataURL());
},1);
};

return w;
}

w.snap(callback)在用户按下某个按钮时调用。问题是在调用 drawImage 之间有一个显着的滞后,并且图像实际上被绘制到画布上。 发生的问题




  • 用户1使用平板电脑,按下按钮, 并发送到服务器。服务器接收到一个空白,透明的图像。 (这与 html5 canvas toDataURL返回空白图片 - 数据不一样因为它是空白的)

  • 几分钟后,用户2使用平板电脑并按下按钮,并且他们的照片被捕捉 。

  • 稍后,用户3执行相同的操作,服务器将获取用户2的照片。


所以我猜测调用 toDataURL()是返回旧数据,因为 drawImage 不。 (我读的地方,它是异步,但我不能确认,不能找到任何方式附加事件,当它完成绘制。)



尝试:




  • snap()中的超时更改为各种值。我尝试的最高的是2000年,但同样的问题发生。 (如果任何人提出更高的数字,我很乐意尝试他们,但我不想走得更高,因为如果我走得太高,用户3可能有照片拍摄之前,我甚至处理用户2的

  • 当页面首次加载时,画布会显示一些东西,但是没有解决它 - 当用户1被拍摄时,服务器收到了
  • 使用 getElementById ,

    还有几个注意事项:

    >


    • 在Chrome和Opera上的计算机(macbook air)上可以正常播放。


    • AFAIK Opera Mobile是唯一支持 getUserMedia 的Android浏览器,可以通过调试器(使用Opera Dragonfly连接到平板电脑)

    • 如果我从视频中删除 display:none; c $ c>和 canvas ,它可以正常工作(在平板电脑上)。 只有在视频和画布<:code> display:none; 设置时才会出现此问题。



    由于页面是一个单页应用程序,不需要滚动或缩放,一种可能的解决方法是将视频和画布移动到页面下方,然后使用javascript禁用滚动(即滚动到



    >解决方案

    我没有一个很好的解决方案,但我建议不要通过设置它看不见的dom通过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)



    也为什么不使用

      canvas.toDataURL(image / jpg)? 

    编辑:另外,如果你正在设计它,你试过其他浏览器吗?



    编辑2:考虑到它,Canvas还有两个其他选项,让这张照片到位,你会想看看两个。那两个是:

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

    - 或 -

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

    这两个忽略你对上下文做的任何缩放,但我发现他们更直接,往往更快。它们是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 p>

    I have a bit of Javascript that runs on an Android tablet, running Opera Mobile 12. The tablet is attached to the wall in an office, so it's used by everyone who works in this office, as a timekeeping system (ie. they use it to clock in/clock out of work). This javascript takes a photo of the user when a certain event is raised, then converts this photo to a data URL so it can be sent to a server. This all runs in the background, though - the video and canvas elements are both set to display:none;.

    Here's the code that handles the webcam interaction:

    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) gets called when the user presses a certain button. The problem is that there is a significant lag between the call to drawImage, and an image actually being drawn to the canvas. Here's the problem that occurs:

    • User 1 users the tablet, presses the button, has their photo "snapped" and sent to the server. The server receives a blank, transparent, image. (It's not the same issue as html5 canvas toDataURL returns blank image - the data being sent to the server is substantially less for the first image, because it's blank)
    • A few minutes later, user 2 uses the tablet and presses the button, and has their photo "snapped". The server receives the photo of user 1.
    • Later, user 3 does the same thing, and the server gets a photo of user 2.

    So I'm guessing the call to toDataURL() is returning old data because drawImage() doesn't . (I read somewhere that it's async, but I can't confirm and can't find any way of attaching an event to when it finishes drawing.)

    I've tried:

    • changing the timeout in snap() to a variety of values. The highest I tried was 2000, but the same issue occurred. (If anyone suggests higher numbers, I'm happy to try them, but I don't want to go much higher because if I go too high, there's potential for user 3 to have their photo taken before I've even processed user 2's photo, which means I might lose it entirely!)
    • having the canvas draw something when the page first loads, but that didn't fix it - when user 1 was photographed, the server received whatever photo was taken when the page loaded, instead of the photo of user 1.
    • "getting" the canvas element again, using getElementById, before calling toDataURL.

    A few more notes:

    • This works fine on my computer (macbook air) in Chrome and Opera.
    • I can't reliably replicate it using a debugger (linking to the tablet using Opera Dragonfly).
    • AFAIK Opera Mobile is the only Android browser that supports getUserMedia and can thus take photos.
    • If I remove the display:none; from the video and canvas, it works correctly (on the tablet). The issue only occurs when the video and canvas have display:none; set.

    Because the page is a single page app with no scrolling or zooming required, a possible workaround is to move the video and canvas below the page fold, then disable scrolling with javascript (ie. scroll to the top whenever the user scrolls).

    But I would rather a proper fix than a workaround, if possible!

    解决方案

    I don't have a very good solution but I would suggest not handling an invisible canvas through the dom by setting it invisible.

    Instead of

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

    Try

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

    This way it's separate from the DOM.

    Also Why not use

    canvas.toDataURL("image/jpg")?
    

    EDIT: Also, if you're designing it, have you tried the other browsers out there? Whats restricting you to Opera over the other browsers available or using phonegap?

    EDIT2: Thinking about it, Canvas also has two other options for getting that photo into place that you would want to look in two. Those two being:

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

    -or-

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

    These two ignore any scaling you've done to the context but I've found that they are much more direct and often faster. They are a solid alternative to toDataURL and drawImage but the image data you put and get from these are encoded as an array in the form:

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

    you can find documentation for them here:

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

    这篇关于上下文drawImage / canvas toDataURL在opera手机上显着滞后的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆