显示所有当前访客的游标

时间:2014-12-20 10:44:01

标签: javascript node.js meteor cursor-position

在每个浏览器窗口中显示所有当前访问者光标的最佳方法是什么?

这是否可以实现,没有太多滞后?

这是我对meteor js的尝试:

http://meteorpad.com/pad/rCSsroc4G4gYQGkAY/Leaderboard(请注意名称,不能改变它吗?)

http://allofthecursors.meteor.com/

cursors.js:

Cursors = new Mongo.Collection("Cursors");

if (Meteor.isClient) {
  Meteor.startup(function () {
      if(!Session.get('cursorId')) {
        // todo: not unique enough!
        var cursorId = new Date();

        Session.set('cursorId', cursorId);
        Meteor.call('initCursor', cursorId);
      }
  });

  Template.cursor.helpers({
    cursor: function() {
      return Cursors.findOne({ cursorId: Session.get('cursorId') });
    },
    cursors: function() {
      return Cursors.find({ cursorId: { $ne: Session.get('cursorId') } });
    }
  });

  Template.cursor.events({
    "mousemove": function(event) {
      var x = event.pageX,
          y = event.pageY,
          cursorId = Session.get('cursorId');

      Meteor.call('updateCursor', cursorId, x, y);
    }
  });
}

if (Meteor.isServer) {

  Meteor.methods({
    'initCursor': function(cursorId) {
        Cursors.insert({
          cursorId: cursorId,
          x: 0,
          y: 0
        });
    },
    'updateCursor': function(cursorId, x, y) {
      Cursors.update(
        { cursorId: cursorId }, 
        { $set: { x: x, y: y }}
      );
    }
  });
}

cursors.html

<head>
  <title>cursors</title>
</head>
<body>

    {{> cursor}}

</body>

<template name="cursor">
    <div class="cursors-area">
        {{#each cursors}}
            <div class="cursor" style="top: {{y}}px; left: {{x}}px;"></div>
        {{/each}}

        <div class="my-cursor">
            {{cursor.cursorId}}: {{cursor.x}}, {{cursor.y}}
        </div>
    </div>
</template>

cursors.css

html, body {
    margin: 0;
    padding: 0;
}

.cursors-area {
    height: 100vh;
}

.cursor {
    position: fixed;
    width: 11px;
    height: 17px;
    background-image: url(cursor.png);
}

感谢evrybady的回应。这是更新版本。

添加了流包: $ meteor add lepozepo:streams

客户端集合仅用于访问被动功能。

cursors_2.js

Stream = new Meteor.Stream('public');

if( Meteor.isClient ) {

  Cursors = new Mongo.Collection(null);

  Template.cursor.events({
    'mousemove': function(event) {

      if (Meteor.status().connected) {
        Stream.emit('p', { 
          _id: Meteor.connection._lastSessionId,
          x: event.pageX, 
          y: event.pageY 
        });
      }

    }
  });

  Stream.on('p', function(p) {

    // how can I change this? 

    if( Cursors.findOne(p._id) === undefined ) {

      Cursors.insert({
        _id: p._id,
        x: p.x,
        y: p.y
      });

    } else {

      Cursors.update(p._id, {
          $set: {
            x: p.x,
            y: p.y
          }
        }
      );
    }

  });

  function getCursors() {
    return Cursors.find();
  }
  var throttledGetCursors = _.throttle(getCursors, 50);

  Template.cursor.helpers({
    cursors: throttledGetCursors
  });
}

2 个答案:

答案 0 :(得分:1)

基本上有两种方法可以解决这个问题。

  1. 第一种方法是使用内置的API进行客户端 - 服务器 - 客户端通信和记录保存,即集合。这样做的好处在于它非常简单,并且可以为您提供反应和沟通。如果沿着这条路走下去,我认为您当前的设置过于复杂 - 您正在使用方法来传达来自每个客户端的位置变化,然后使用livedata在集合同步时再次将其传回。为什么不直接从客户端写入集合?我建议这样的事情:
  2. <强>客户端

    Template.body.events({
        'mousemove': function(event) {
            if (Meteor.status().connected) {
                Cursors.update(Meteor.connection._lastSessionId, {
                    $set: {
                        x: event.pageX,
                        y: event.pageY
                    }
                });
            }
        }
    });
    

    服务器

    Meteor.onConnection(function(connection) {
        Cursors.insert({
            _id: connection.id,
            x: 0,
            y: 0
        });
        connection.onClose(function() {
            Cursors.remove(connection.id);
        });
    });
    

    除了避免使用会话变量之外,还使用会话ID为每个客户端提供唯一的游标ID,并在断开连接时将其从集合中删除。从安全角度来看,这也是首选,因为它允许您阻止用户更新不共享其连接ID的游标(通过允许/拒绝),以防万一。或者

    1. 但是,您仍然需要将内容从MongoDB中删除,这将导致一些延迟。正如@sbking指出的那样,lepozepo:streams包(docs here)允许您更接近原始websocket进行通信,虽然它将涉及更多的管道,但将导致更少的延迟。 2015年12月伦敦DevShop对此进行了一些讨论,视频即将推出。如果有人可以为纯粹的服务器 - 客户端消息(独立于集合)编写集合,那将是很好的,但我认为目前不存在。
    2. 另外,同意@sbking您应该使用Underscore(限制)来更新更新。

答案 1 :(得分:0)

使用WebRTC进行此操作。谷歌吧。

基本上你将使用一些JavaScript将两个浏览器连接在一起,Meteor将发送握手,然后两个浏览器可以通话。从这里,你可以做各种数据密集型的东西,而不会炸毁Meteor或你的客户。 EZ。 PZ。