RXJS在html5画布上绘制线条 [英] RXJS draw line on html5 canvas

查看:149
本文介绍了RXJS在html5画布上绘制线条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现相同的效果,我发布在这里使用反应式扩展JavaScript(RX-JS)。
我对如何做到有点困惑。
这是页面:

 <!DOCTYPE html> 
< html>
< head>
< title>拖放< / title>
< / head>
< style type =text / css>

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

< / style>
< body>
< canvas id =canvaswidth = 300 height = 300>< / canvas>
< script type =text / javascriptsrc =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 =
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 clientY - offsetY);
$(#movelog)。html(Move:+ mouseX +/+ mouseY);

var ctx = canvas.getContext(2d);
//一些清理代码
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事件创建observable。

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

但我不知道如何组合它们。我想应该开始观察mousedown,然后收集所有的动作,直到mouseup被提出,并在whil重画线从起点到鼠标在mousemove的当前点。
你有什么想法吗?非常感谢。



从美国本土化到人类的最低价。

这是我的代码在Brandon的回答后:



  $(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当鼠标被触发时对引用的引用
//然后使用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,0,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)); 

接下来,将此事件流投影到上一个,当前元组。

  var moves = drag 
.scan({},function 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 ,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,
...
});


I'm trying to achieve the same effect I'm posting here using Reactive Extensions for Javascript (RX-JS). I'm a bit puzzled on how to do it. Here is the page:

      <!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>

I think I should create observables for the mouseDown, mouseMove and mouseUp events.

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

but I don't know how to combine them. I think should start observing the mousedown, then collect all the moves until the mouseup is raised, and in the whil redraw the line from the starting point to the current point where the mouse is during the mousemove. Do you have any ideas? Thanks a lot.

°°°°°°°°°°°°°°°°°°°°°°EDIT°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°

Here is my code after the answer by Brandon:

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

解决方案

First, combined the streams so you have a stream of events that represent a single drag.

var drag = mouseDown.first().concat(mouseMove.takeUntil(mouseUp));

Next, project this stream of events into a stream of previous,current tuples.

var moves = drag
    .scan({}, function(acc, x) {
        return { previous: acc.current, current: x };
    })
    .skip(1);

Now we have a stream that only works the first time. When it ends, we want to start listening for the next drag:

var allMoves = moves.repeat();

Finally, subscribe:

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

Putting it all together without all of the intermediate variables:

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

这篇关于RXJS在html5画布上绘制线条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆