0

我尝试实现一种基于简单 JPEG 文件的视频流。在我的服务器上,外部相机正在循环创建 JPEG。我只想在我的 GWT 应用程序中包含这张图片。

我通过计时器重新加载图片的第一个想法非常简单但不太好:客户端为每个重新加载周期打开一个连接,并且图片闪烁(至少在 Firefox 中)。

我该如何解决这些问题?我正在考虑类似“Web-Sockets”的东西,但我真的不知道该怎么做。我想避免每次重新加载都使用单个连接。我的想法是有一个类似开放连接的东西,它只根据客户的要求提供一张新图片。

交换图片时如何避免闪烁?

欢迎任何想法!

问候,范达伦

4

1 回答 1

0

避免闪烁的解决方案是将两个图像绝对定位在同一位置。计时器将在每一帧中交替加载一个或另一个。为每个图像设置一个load处理程序,以便在加载图像时更改 z-index 并重新启动计时器。

向图像 url 添加一个额外的参数,使浏览器每次都要求服务器绕过其缓存。

如果帧之间的时间很短,通常浏览器会在服务器中正确配置keep-alive的情况下重复使用相同的连接 。它通常以 5-15 秒的典型值启用,您可以增加该值,因此如果您的 .jpg 图像以这种周期性更新,您不必担心并寻找更好的解决方案。

我基于这些想法提出了一个 UI 解决方案。但是,如果您使用 websocket/comet 机制为您提供 base64 格式的最后一个 .jpg 文件(只需通过返回的值更改 url),它也会起作用。

GWT 代码:

public void onModuleLoad() {

  final Image i1 = new Image();
  i1.setWidth("400px");

  final Image i2 = new Image();
  i2.setWidth("400px");

  AbsolutePanel panel = new AbsolutePanel();
  panel.add(i1, 0, 0);
  panel.add(i2, 0, 0);
  panel.setSize("600px", "400px");

  RootPanel.get().add(panel);

  // You could change this by base64 data if you use comet/websockets
  String url = "my_image_url.jpg?";

  final Timer loadNext = new Timer() {
    boolean b;
    int c;
    public void run() {
      // the counter parameter forces to load the next frame instead of using cache
      if (b  = !b) {
        i1.setUrl(url + c++);
      } else {
        i2.setUrl(url + c++);
      }
    }
  };

  i1.addLoadHandler(new LoadHandler() {
    public void onLoad(LoadEvent event) {
      i1.getElement().getStyle().setZIndex(1);
      i2.getElement().getStyle().setZIndex(0);
      loadNext.schedule(1000);
    }
  });

  i2.addLoadHandler(new LoadHandler() {
    public void onLoad(LoadEvent event) {
      i1.getElement().getStyle().setZIndex(0);
      i2.getElement().getStyle().setZIndex(1);
      loadNext.schedule(1000);
    }
  });

  loadNext.schedule(1000);
 }

如果你想使用gwtquery,代码显然更小:

  // You could change this by base64 data if you use comet/websockets
  final String url = "my_image_url.jpg?";

  final GQuery images = $("<img/><img/>").appendTo(document);
  images.css($$("position: fixed, top: 10px, left: 600px, width: 400px"));

  final Timer timer = new Timer() {
    int c;
    public void run() {
      images.eq(c%2).attr("src", url + c++);
    }
  };

  images.bind("load", new Function(){
    public void f() {
      $(this).css($$("z-index: 1")).siblings("img").css($$("z-index: 0"));
      timer.schedule(1000);
    }
  });

  timer.schedule(1000);
于 2013-04-18T14:36:30.973 回答