1

语境

我正在制作一个应用程序,用于在无法访问 Internet 的无线 LAN 中向大约 50 名观众展示同步的 HTML5 幻灯片。

我在其中一台计算机上运行 Node.js 服务器,并通过 Socket.IO 与 50 个客户端连接(顺便说一句,其中只有一个控制演示)。

硬件是一台家用无线 802.11b/g 路由器和 50 台移动设备(平板电脑、上网本、智能手机)。

问题

当幻灯片开始时,客户端需要很长时间(大约 10 分钟或更长时间才能看到 5 MB 幻灯片)才能看到它,因为路由器必须同时将完整的幻灯片发送给所有客户端。

我的幻灯片看起来如何

<html>
  <head>
    <title>My Slideshow</title>
    <script src="javascripts/slidesplayer.js"></script>
    <link rel="stylesheet" href="/stylesheets/style.css">
  </head>

  <body>    
    <div id="slides-containter">

      <div class="slide" id="slide_1">
        <!--Contents such as images, text, video and audio sources -->
      </div>

      <div class="slide" id="slide_2">
        <!--Contents -->
      </div>

      <!--A bunch of slides here-->

    </div>
    <script>
      // Here I load the slides
    </script>
  </body>
</html>

我想做什么

一开始,我想加载slides-container元素完全为空。

然后,当我浏览幻灯片时,我想从服务器获取div代表下一张幻灯片,并将其附加到 DOM 以便只有在完成后,客户端才开始下载图片和其他内容那张幻灯片(因此,大大减少了我的网络过载)。

另一个相关的事实是,幻灯片(包括slidesplayer.js)是从将 PowerPoint 演示文稿解析为这种 HTML5 格式的外部软件自动生成的,我们将使用许多已经在 PowerPoint 中制作的演示文稿。

我的第一印象是我应该通过使用 jQuery-ajax 来实现这一点,但我不知道如何做到这一点,因为我的想法只是将div.slide元素复制到单独的文件中。

更新: 这个答案建议在显示之前使用 jQuery 进行 DOM 操作。似乎 jQuery 每次操作 DOM 对象时都会请求资源,即使它没有插入到当前的 DOM 中。因此,一种可能的解决方案是仅使用字符串。你可以在这个这个问题中看到更多关于这个问题的信息。

4

3 回答 3

2

一种解决方案是将其视为前端解决方案。可以说,前端在任何时候都应该只吃尽可能多的东西。

我假设它是外部资源(图像等)而不是幻灯片标记本身,它占了这 5MB 的大部分,在这种情况下,DOM 不应该尝试调用这些资源,直到它们是必要的。

我建议将整个幻灯片文档提供给 ajax 调用,但只在每张幻灯片被调用时引入标记。像这样的东西:

$.ajax('path/to/slides', {
  async:    false,
  complete: function ajaxCallback(slidesDOM){
    // Pull out the individual slides from your slideshow HTML 
    $slides = $(slidesDOM).find('.slide');

    // For each of these...
    $slides.each(function prepareSlide(){
      // Store a reference to the slide's contents
      var $slideContent = $($(this).html());
      // Empty the contents and keep only the slide element itself
      var $slideWrapper = $(this).empty();

      $slideWrapper
        // Put the slide where you want it
        .appendTo('.slidesContainer')
        // And attach some kind of event to it 
        // (depending on how your slideware works, you might want to bind this elsewhere)
        .on('focus', function injectContent(){
          // Put the content in — NOW external resources will load
          $slideWrapper.append($slideContent);

          // Unbind this function trigger
          $slideWrapper.off('focus', injectContent);
        });
    })
  }
});
于 2012-12-21T15:16:16.230 回答
1

1)您不应该使用 SocketIO 流式传输有效负载。插座是为低负载而设计的。如果您需要整体传输,我建议您使用标准的 HTTP AJAX 请求。然后,您可以使用 Socket.IO 来控制您所在的幻灯片。

2)尝试AngularJS。他们基本上已经为您完成了有关视图切换的所有思考(这基本上就是您正在做的事情)。他们有一个很棒的教程,这很有帮助。

3)为了简化您的 Socket 调用,我建议在客户端和服务器端都使用 ConversationJS。

于 2012-12-21T15:05:02.820 回答
1

正如我在问题中所说,操作 DOM 元素将导致浏览器下载资源,即使您没有在 DOM 中插入使用该资源的元素。

就我而言,我能做的最好的解决方案是至少对标签使用某种延迟加载img(但它可以很容易地扩展到其他标签,例如audioand video)。

我所做的是将src属性替换为另一个名称(在本例中),并向所有 img 标签xsrc添加自定义空属性。src

<img id="someImg" src="#" xsrc="foo.png"></img>

然后,使用 jQuery,我将src属性值更改为xsrc需要下载图像时的属性值。

// When I want the image to be downloaded from the server
$('#someImg').attr( 'src' , $('#someImg').attr('xsrc') )

你可以在我已经提到的问题(这个这个)中看到更多关于这个背后的想法。

于 2013-01-03T15:36:01.477 回答