RXJS 在 html5 画布上绘制线条



我试图达到与使用Reactive Extensions for 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>

我想我应该为mouseDown,mouseMove和mouseUp事件创建可观察量。

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

但我不知道如何组合它们。我认为应该开始观察鼠标向下,然后收集所有动作,直到鼠标向上抬起,并在鼠标移动期间重新绘制从起点到鼠标所在点的线。你有什么想法吗?多谢。

°°°°°°°°°°°°°°°°°°°°°°编辑°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°

这是我在布兰登回答后的代码:

              $(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,
        ...
    });

相关内容

  • 没有找到相关文章

最新更新