【问题标题】:How to draw image to canvas, when the image changes, not the URI?当图像更改而不是URI时,如何将图像绘制到画布?
【发布时间】:2014-02-05 06:15:22
【问题描述】:

这是我如何在画布上绘制图像的基本实现。

  var canvas = document.getElementById('myCanvas');
  var context = canvas.getContext('2d');
  var imageObj = new Image();

  function drawImg(x, y) {
     imageObj.onload = function() {
       context.drawImage(imageObj, x, y);
     };
     imageObj.src = 'http://www.mysite.com/temp.jpg';
  }

我有一个服务器端图像渲染脚本,我正在将图像写入相同的文件位置,例如:“temp.jpg”。当图像更改时,我正在使用 Ajax 提示浏览器,然后我运行该函数以再次加载图像。但是,似乎由于 URL 始终相同,所以加载的第一张图像被缓存并且永远不会重绘。

我找到了几种解决方案,但我不确定哪种方案最有效或真正的最佳解决方案。一些建议包括稍微操纵带有时间戳的 URL,并且我已经看到了一些对流媒体的引用。

一些关键点:

  • 我不想清除画布,我希望最近的图像位于前一个图像之上,以防 x,y 坐标发生变化或图像大小不同,它应该分层。
  • 我真的不想为每个新图像更改图像文件名,这似乎有点过头了。

谢谢。

编辑:

决定将我的 github 项目包含在我正在开发的 socket.io 版本中。我正在制作大约 5 个不同的版本,但这是我主要跟踪的版本。随意撕开它我确信在内存管理方面我有一些不好的做法。 https://github.com/Pwn9/tcp-io-bridge

【问题讨论】:

    标签: javascript html image canvas


    【解决方案1】:

    IMO,最好的解决方案是为图像添加一个时间戳(您也可以添加一个随机值,只是为了确保)作为参数。这避免了必须存储特定的变量计数器,并且非常容易实现。也许是这样的:

    "?" + +new Date() + "_" + Math.random ()
    

    您可能还只是想完全避免缓存,但如果您没有将所有图像转换为画布对象,这会出现问题,因为在大多数基于 Webkit 的浏览器中,如果介于以下情况之间,则在刷新之间禁用图像缓存 -页面缓存也被禁用..

    [edit:] 或者,换句话说,在基于 Webkit 的浏览器中,如果您使用 Javascript 重新加载某些内容并且您的标题显示“过期”,则将重新请求该图像。在 IE11 和 Firefox 中,即使禁用了缓存,图像也会一直缓存到页面刷新。

    http://code.google.com/p/chromium/issues/detail?id=336292

    【讨论】:

    • 将我的服务器头设置为无缓存的组合是迄今为止最好的解决方案。
    【解决方案2】:

    也许你可以大致做这样的事情:

      var i = 0;
    
      var canvas = document.getElementById('myCanvas');
      var context = canvas.getContext('2d');
      var imageObj = new Image();
    
      function drawImg(x, y) {
         imageObj.onload = function() {
           context.drawImage(imageObj, x, y);
         };
         imageObj.src = 'http://www.mysite.com/temp.jpg?' + i;
         i++;
      }
    

    这样你会得到一个像这样的网址列表:

    这似乎让 Chrome 发送了一个网络请求,就像你保持 url 一样,根本没有发送任何网络请求。

    我在 Chrome 中进行了测试,这确实会强制加载新图像。我还将您的标头设置为不缓存该网址。

    我现在正在测试其他几个浏览器。

    【讨论】:

    • 这不会为每个请求创建一个缓存图像吗?或者我可以通过不允许通过 html 标头进行缓存来处理这个问题吗?到目前为止,这一直是我倾向于的解决方案。
    • 是的,这就是您在 http 响应中不设置缓存标头的原因
    【解决方案3】:

    在处理类似于小型单页应用程序的复杂表单页面时遇到缓存问题,我通常的解决方案是在响应中设置各种无缓存标头。这意味着您需要能够在您的 Web 服务器上进行配置或在服务器端代码中进行配置。

    这些是典型的跨浏览器标头:

    Cache-Control: no-cache, no-store, must-revalidate
    Pragma: no-cache
    Expires: 0
    

    有关服务器端代码示例,请参阅此答案: https://stackoverflow.com/a/2068407/2836187

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多