我是Reactive Extensions和JavaScript的新手。有人可以帮我拧开以下代码吗?来自Matthew Podwysocki's Introduction to the Reactive Extensions to JavaScript

<html>
<head>
 <title>Learning ReactiveExtensions</title>
 <!--scripts-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script src="rx.min.js" type="text/javascript"></script>
<script type="text/javascript">

$(document).ready(function() {
var mouseDragMe = $("#mouseDragMe").context;

var mouseMove = Rx.Observable.FromHtmlEvent(mouseDragMe, "mousemove");
var mouseUp = Rx.Observable.FromHtmlEvent(mouseDragMe, "mouseup");
var mouseDown = Rx.Observable.FromHtmlEvent(mouseDragMe, "mousedown");

    var mouseMoves = mouseMove
.Skip(1)
.Zip(mouseMove, function(left, right) {
    return { x1 : left.clientX,
             y1 : left.clientY,
             x2 : right.clientX,
             y2 : right.clientY };
});

    var mouseDrags = mouseDown.SelectMany(function(md) {
return mouseMoves.TakeUntil(mouseUp);

    mouseDrags.Subscribe(function(mouseEvents) {
$("#results").html(
    "Old (X: " + mouseEvents.x1 + " Y: " + mouseEvents.y1 + ") " +
    "New (X: " + mouseEvents.x2 + " Y: " + mouseEvents.y2 + ")");
});
});
});
</script>
</head>
<body>
<div id="mouseDragMe" style="border:solid 1px red;">
    i am a rx newbie
</div>
</body>
</html>

最佳答案

那里对此有描述。我建议查看this video about Writing your first Rx Application。代码使用C#,但无论使用哪种编程语言,概念都完全相同。

本质上你想了解三件事


将一系列事件概念化为序列。就像一个
数组是空间中的数据序列,事件可以被认为是
时间(或运动)中的数据顺序。
运算符(即SkipZipSelectManyTakeUntil
订阅语义


在这种情况下,我们有3个源序列。 mouseMovemouseUpmouseDown

每次移动鼠标时,mouseMove序列都会推送鼠标坐标的值。例如,如果鼠标从屏幕的左上角开始,然后沿对角线向下移动,则笔直穿过屏幕,您可能会在序列上看到诸如{0,0}{10,10}{20,10}之类的值。

mouseUpmouseDown发布的值并不有趣,只是发布它们的时间点很有趣。

实际的“拖动”问题要求我们知道何时按下鼠标按钮,以及按下鼠标时鼠标在何处以及释放按钮时在何处。我们获得这些头寸的差值的方法是获取最终头寸的值,再减去原始头寸的值。更好的是,如果我们可以获取所有中间增量值,以便可以对运动进行动画处理。如果我们采用上面的序列,则要获得运动增量,我们希望拥有原始序列,然后偏离一个序列

Original { 0, 0}, {10,10}, {20,10}
offby1   {10,10}, {20,10}


这使我们能够计算出增量来计算运动(而不仅仅是位置)。

Original { 0, 0}, {10,10}, {20,10}
offby1   {10,10}, {20,10}
delta    {10,10}, {10, 0}


我们可以使用Rx实现此目的的方法是首先使用Skip(1)跳过一个值。这将创建我们的offby1序列。接下来,我们要成对组合值。 Zip函数为我们提供了此功能(my blog post about Combining sequences with Zip中有更多信息)。

我们可以重写上面的代码

var mouseMoves = mouseMove
.Skip(1)
.Zip(mouseMove, function(left, right) {
    return { x1 : left.clientX,
             y1 : left.clientY,
             x2 : right.clientX,
             y2 : right.clientY };
});


成为

var offby1 = mouseMove.Skip(1);
var mouseMoves = offby1.Zip(mouseMove, function(left, right) {
    return { x1 : left.clientX,
             y1 : left.clientY,
             x2 : right.clientX,
             y2 : right.clientY };
});


一旦有了对,就需要应用newValue-OldValue=delta的简单数学。
这给出了我们的增量序列,这实际上是我们的运动序列。

var offby1 = mouseMove.Skip(1);
var mouseMoves = offby1.Zip(mouseMove, function(current, last) {
    return { x : current.clientX-last.clientX,
             y : current.clientY-last.clientY };
});


现在,我们只想在鼠标按下时获取值。为此,我们使用SelectMany运算符。也就是说,对于来源中的每个值,请从该来源中获取0个或多个值。在我们的案例中,每次发生mouseDown事件时,我们都希望获取所有增量事件(作为mouseMoves)。

var mouseDrags = mouseDown.SelectMany(function(md) { return mouseMoves;});


但是,我们只希望继续接收它们,直到发生相应的mouseUp事件为止。为此,我们TakeUntil mouseUp事件产生一个值。

var mouseDrags = mouseDown.SelectMany(function(md) {
  return mouseMoves.TakeUntil(mouseUp);
});


现在我们已经完成了所有这些工作,我们通常将这些移动应用于UI元素的Position / Margin / offset。它出现在示例中,尽管我们只打印了该值。

10-05 21:06
查看更多