0

我是Reactive ExtensionsJavaScript的新手。有人可以帮我解开以下代码吗?它来自Matthew Podwysocki 的 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>
4

1 回答 1

3

那里有这方面的描述。我建议您观看有关编写您的第一个 Rx 应用程序的视频。代码在 C# 中,但无论编程语言如何,概念都是完全相同的。

本质上你想了解三件事

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

在这种情况下,我们有 3 个源序列;mouseMove,mouseUpmouseDown.

mouseMove每次移动鼠标时,该序列都会推送一个鼠标坐标值。例如,如果鼠标从屏幕的左上角开始并沿对角线向下移动,那么您可能会在序列上看到类似{0,0}, {10,10},的值。{20,10}

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

“拖动”的实际问题需要我们知道鼠标按钮何时被按下,鼠标按下时鼠标所在位置的增量,以及释放按钮时鼠标所在位置。我们可以获得这些位置的增量的方法是取最终位置的值并减去原始位置的值。更好的是,如果我们可以获得所有的中间 delta 值,以便我们可以为运动设置动画。如果我们采用上面的序列,为了获得运动的增量,我们希望拥有原始序列和偏移一个序列

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函数为我们提供了这个(在我的博客文章中更多关于将序列与 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发生事件时,我们都希望获得所有的 delta 事件(如mouseMoves)。

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

However we only want to keep receiving them until a corresponding mouseUp event happens. To do this we TakeUntil the mouseUp event produces a value.

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

Now that we have all this plumbing done, we usually apply those movements to the Position/Margin/offset of a UI element. It appears in the example, we just print the value though.

于 2012-09-19T12:48:47.397 回答