Javascript RXJS在html5画布上绘制线条

Javascript RXJS在html5画布上绘制线条,javascript,html,canvas,system.reactive,rxjs,Javascript,Html,Canvas,System.reactive,Rxjs,我正在尝试使用Javascript的反应式扩展(RX-JS)实现我在这里发布的相同效果。 我对怎么做有点困惑。 以下是网页: <!DOCTYPE html> <html> <head> <title>drag and drop</title> </head> <style type="text/css"> canvas {

我正在尝试使用Javascript的反应式扩展(RX-JS)实现我在这里发布的相同效果。 我对怎么做有点困惑。 以下是网页:

      <!DOCTYPE html>
      <html>
      <head>
        <title>drag and drop</title>
      </head>
      <style type="text/css">

      canvas {
        border:1px solid steelblue;
        background-color: whitesmoke;
      }

      </style>
      <body>
        <canvas id="canvas" width=300 height=300></canvas>
        <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
        <script type="text/javascript">
        $(function() {
            var canvas = document.getElementById("canvas");
            var ctx = canvas.getContext("2d");

            var canvasOffset = $("#canvas").offset();
            var offsetX = canvasOffset.left;
            var offsetY = canvasOffset.top;

            var drawing = false;
            var mouseX = 0;
            var mouseY = 0;


            function handleMouseDown(e) {
                mouseX = parseInt(e.clientX - offsetX);
                mouseY = parseInt(e.clientY - offsetY);         
                drawing= true;                
        }

        function handleMouseUp(e) {             
            drawing = false;    
        }
        function handleMouseMove(e) {
            if(drawing){
              mouseeX = parseInt(e.clientX - offsetX);
              mouseeY = parseInt(e.clientY - offsetY);
              $("#movelog").html("Move: " + mouseX + " / " + mouseY);

                var ctx =  canvas.getContext("2d");
                // some cleanup code
                ctx.save();
                ctx.setTransform(1, 0, 0, 1, 0, 0);
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                ctx.restore();          
                ctx.beginPath();
                ctx.moveTo(mouseX,mouseY);
                ctx.lineTo(mouseeX,mouseeY);
                ctx.stroke();
             }
        }

        $("#canvas").mousedown(function(e) {
            handleMouseDown(e);
        });
        $("#canvas").mousemove(function(e) {
            handleMouseMove(e);
        });
        $("#canvas").mouseup(function(e) {
            handleMouseUp(e);
        });

      });
      </script> 
      </body>
      </html>
但我不知道如何把它们结合起来。我认为应该开始观察鼠标向下移动,然后收集所有移动,直到鼠标上升,同时在鼠标移动期间重新绘制从起点到鼠标所在当前点的线。 你有什么想法吗?非常感谢

编辑

以下是布兰登回答后的代码:

              $(function() {

                  var canvas = document.getElementById('canvas');
                  var ctx = canvas.getContext("2d");
                  var canvasOffset = $("#canvas").offset();
                  var offsetX = canvasOffset.left;
                  var offsetY = canvasOffset.top;

                  var mouseDown = Rx.Observable.fromEvent($("#canvas"), 'mousedown');
                  var mouseMove = Rx.Observable.fromEvent($("#canvas"), 'mousemove');
                  var mouseUp = Rx.Observable.fromEvent($("#canvas"), 'mouseup');

                  // keep a reference to the pisition when the mouse down was fired
                  // then flatten the stream with concatAll


                  var traceLineStream = mouseDown.map(function(md) {
                      var movesFromMouseDown = mouseMove.takeUntil(mouseUp);
                      var movesFromMouseDownAndMouseDown = movesFromMouseDown.map(function(mm) {
                          return {
                              mouseDownPoint: md,
                              mouseMovePoint: mm
                          }
                      });
                      return movesFromMouseDownAndMouseDown;
                  }).concatAll();


                  var subscription = traceLineStream.subscribe(
                      function(y) {

                          var mouseDown = y.mouseDownPoint;
                          var mouseMove = y.mouseMovePoint;

                          var mouseDownX = parseInt(mouseDown.clientX - offsetX);
                          var mouseDownY = parseInt(mouseDown.clientY - offsetY);               

                          var mouseMoveX = parseInt(mouseMove.clientX - offsetX);
                          var mouseMoveY = parseInt(mouseMove.clientY - offsetY);

                          ctx.save();
                          ctx.setTransform(1, 0, 0, 1, 0, 0);
                          ctx.clearRect(0, 0, canvas.width, canvas.height);
                          ctx.restore();
                          ctx.beginPath();
                          ctx.moveTo(mouseDownX, mouseDownY);
                          ctx.lineTo(mouseMoveX, mouseMoveY);
                          ctx.stroke();

                      },
                      function(e) {
                          console.log('onError: ' + e.message);
                      },
                      function() {
                          console.log('onCompleted');
                      });
              });

首先,组合这些流,这样就有了一个表示单个拖动的事件流

var drag = mouseDown.first().concat(mouseMove.takeUntil(mouseUp));
接下来,将此事件流投影到
previous、current
元组流中

var moves = drag
    .scan({}, function(acc, x) {
        return { previous: acc.current, current: x };
    })
    .skip(1);
现在我们有一个只在第一次工作的流。当它结束时,我们要开始监听下一次拖动:

var allMoves = moves.repeat();
最后,请订阅:

allMoves.subscribe(function (move) {
    var mouseX = move.previous.clientX - offsetX,
        mouseY = move.previous.clientY - offsetY,
        mouseeX = move.current.clientX - offsetX,
        mouseeY = move.current.clientY - offsetY,
    ...
});
将其全部放在一起,不包含所有中间变量:

mouseDown
    .first()
    .concat(mouseMove.takeUntil(mouseUp))
    .scan({}, function(acc, x) {
        return { previous: acc.current, current: x };
    })
    .skip(1)
    .repeat()
    .subscribe(function (move) {
        var mouseX = move.previous.clientX - offsetX,
            mouseY = move.previous.clientY - offsetY,
            mouseeX = move.current.clientX - offsetX,
            mouseeY = move.current.clientY - offsetY,
        ...
    });

嗨,布兰登,谢谢你的回答。这不完全是我想要的,但却是灵感的源泉。我努力了,得到了我想要的。
mouseDown
    .first()
    .concat(mouseMove.takeUntil(mouseUp))
    .scan({}, function(acc, x) {
        return { previous: acc.current, current: x };
    })
    .skip(1)
    .repeat()
    .subscribe(function (move) {
        var mouseX = move.previous.clientX - offsetX,
            mouseY = move.previous.clientY - offsetY,
            mouseeX = move.current.clientX - offsetX,
            mouseeY = move.current.clientY - offsetY,
        ...
    });