在画布上绘图会导致行从第一点开始

时间:2017-05-02 05:34:55

标签: javascript html5 canvas drawing

我正在制作一个简单的拖动来在画布上绘制脚本。问题在于,当我绘制一条线来连接鼠标位置的点时,画布会从一些随机点绘制额外的线条,但始终从初始点开始。

以下是查看问题的示例:http://sktch.io/988111

我在一次这样的鼠标移动中捕获了数据,并手动完成了每个点的绘制,我可以确认问题没有得到解决。令我恼火的是,如果我手动执行moveTo和lineTo以获取某些任意点,则代码可以正常工作。鼠标拖拽点存在一些问题。据我所知,收集的积分没有问题。

任何指针都表示赞赏。我已经在每个单循环迭代或者beginpath中尝试了各种修改,例如beginPath,moveto,lineto和stroke,并且在循环中 - moveto,lineto,然后在循环外部进行描边。相同的结果。

有问题的代码包含在底部。

var App = (function() {
    var canvas, currentLayer, paint = false, context, socket, room, currentTool = 'line',
    keysrt = function(key,desc) {
        return function(a,b){
            return desc ? ~~(a[key] < b[key]) : ~~(a[key] > b[key]);
        }
    },
    reDraw = function() {
        if (context) {
            context.clearRect(0, 0, canvas.offsetWidth, canvas.offsetHeight);
            Object.keys(layers).sort().forEach(function(key) {
                let layer = layers[key];
                switch(layer.getTool()) {
                    case 'line':
                        var data = layer.getData().sort(keysrt('time'));
                        if(data.length > 1) {
                            for(var i = 1; i < data.length; i++) {
                                context.beginPath();
                                context.moveTo(data[i-1]['value'][0], data[i-1]['value'][1]);
                                context.lineTo(data[i]['value'][0], data[i]['value'][1]);
                                context.stroke();
                            }
                        }
                        break;
                    case 'eraser':
                        var data = layer.getData().sort(keysrt('time'));
                        if(data.length > 0) {
                            for(var i = 0; i < data.length; i++) {
                                context.clearRect(data[i][0], data[i][1], 4, 4);
                            }
                        }
                        break;
                    case 'clear':
                        context.clearRect(0, 0, canvas.offsetWidth, canvas.offsetHeight);
                        break;
                }
            });
        }
    },
    Layer = function() {
        var data = [], tool, id = new Date().getTime();
        return {
            push: function(time, value) {
                data.push({time: time, value: value})
            },
            toJSON: function() {
                return {
                    data: data,
                    tool: tool,
                    id: id
                }
            },
            setTool: function(t) {
                tool = t;
            },
            getTool: function() {
                return tool;
            },
            getData: function() {
                return data;
            },
            getId: function() {
                return id;
            },
            setId: function(i) {
                id = i;
            },
            setData: function(d) {
                data = d;
            }
        };
    },
    layers = {},
    events = 0;
    press = function (e) {
        var mouseX = (e.changedTouches ? e.changedTouches[0].pageX : e.pageX) - this.offsetLeft, mouseY = (e.changedTouches ? e.changedTouches[0].pageY : e.pageY) - this.offsetTop;
        // add a layer
        paint = true;
        currentLayer = Layer();
        currentLayer.setTool(currentTool);
        layers[currentLayer.getId()] = currentLayer;
        events = 1;
    },
    drag = function (e) {
        var mouseX = (e.changedTouches ? e.changedTouches[0].pageX : e.pageX) - this.offsetLeft, mouseY = (e.changedTouches ? e.changedTouches[0].pageY : e.pageY) - this.offsetTop;
        if (paint) {
            events = events + 1;
            currentLayer.push(new Date().getTime() * 10 + events, [mouseX, mouseY]);
            reDraw()
        }
        e.preventDefault();
    },
    release = function () {
        paint = false;
        if(currentLayer) {
            events = 0;
            reDraw();
        }
        currentLayer = null;
    },
    init = function(id, appendTo, width, height) {
        room = id;
        canvas = document.createElement('canvas');
        canvas.setAttribute('width', width);
        canvas.setAttribute('height', height);
        canvas.setAttribute('id', 'canvas');
        appendTo.appendChild(canvas);

        context = canvas.getContext("2d");

        canvas.addEventListener("mousedown", press, false);
        canvas.addEventListener("mousemove", drag, false);
        canvas.addEventListener("mouseup", release);
        canvas.addEventListener("mouseout", release, false);

        // Add touch event listeners to canvas element
        canvas.addEventListener("touchstart", press, false);
        canvas.addEventListener("touchmove", drag, false);
        canvas.addEventListener("touchend", release, false);
        canvas.addEventListener("touchcancel", release, false);

        document.getElementById('clear').addEventListener("click", function() {
            layer = Layer();
            layer.setTool('clear');
            layers[layer.getId()] = layer;
            reDraw();
        }, false);
    }
    return {
        init: init
    }
})();

1 个答案:

答案 0 :(得分:0)

错误在于您的排序功能,它只返回01

将您的keysrt更改为更具可读性

keysrt = function(key,desc) {
    return function(a,b){
        if(desc){
            if(a[key] < b[key]) return 1;
            if(a[key] > b[key]) return -1;
            return 0;
            }
        else{
            if(a[key] < b[key]) return -1;
            if(a[key] > b[key]) return 1;
            return 0;
            }               
    }

解决了这个问题:

var App = (function() {
  var canvas, currentLayer, paint = false,
    context, socket, room, currentTool = 'line',
    keysrt = function(key, desc) {
      return function(a, b) {
        if (desc) {
          if (a[key] < b[key]) return 1;
          if (a[key] > b[key]) return -1;
          return 0;
        } else {
          if (a[key] < b[key]) return -1;
          if (a[key] > b[key]) return 1;
          return 0;
        }
      }
    },
    reDraw = function() {
      if (context) {
        context.clearRect(0, 0, canvas.offsetWidth, canvas.offsetHeight);
        Object.keys(layers).sort().forEach(function(key) {
          let layer = layers[key];
          switch (layer.getTool()) {
            case 'line':
              var data = layer.getData().sort(keysrt('time'));
              if (data.length > 1) {
                for (var i = 1; i < data.length; i++) {
                  context.beginPath();
                  context.moveTo(data[i - 1]['value'][0], data[i - 1]['value'][1]);
                  context.lineTo(data[i]['value'][0], data[i]['value'][1]);
                  context.stroke();
                }
              }
              break;
            case 'eraser':
              var data = layer.getData().sort(keysrt('time'));
              if (data.length > 0) {
                for (var i = 0; i < data.length; i++) {
                  context.clearRect(data[i][0], data[i][1], 4, 4);
                }
              }
              break;
            case 'clear':
              context.clearRect(0, 0, canvas.offsetWidth, canvas.offsetHeight);
              break;
          }
        });
      }
    },
    Layer = function() {
      var data = [],
        tool, id = new Date().getTime();
      return {
        push: function(time, value) {
          data.push({
            time: time,
            value: value
          })
        },
        toJSON: function() {
          return {
            data: data,
            tool: tool,
            id: id
          }
        },
        setTool: function(t) {
          tool = t;
        },
        getTool: function() {
          return tool;
        },
        getData: function() {
          return data;
        },
        getId: function() {
          return id;
        },
        setId: function(i) {
          id = i;
        },
        setData: function(d) {
          data = d;
        }
      };
    },
    layers = {},
    events = 0;
  press = function(e) {
      var mouseX = (e.changedTouches ? e.changedTouches[0].pageX : e.pageX) - this.offsetLeft,
        mouseY = (e.changedTouches ? e.changedTouches[0].pageY : e.pageY) - this.offsetTop;
      // add a layer
      paint = true;
      currentLayer = Layer();
      currentLayer.setTool(currentTool);
      layers[currentLayer.getId()] = currentLayer;
      events = 1;
    },
    drag = function(e) {
      var mouseX = (e.changedTouches ? e.changedTouches[0].pageX : e.pageX) - this.offsetLeft,
        mouseY = (e.changedTouches ? e.changedTouches[0].pageY : e.pageY) - this.offsetTop;
      if (paint) {
        events = events + 1;
        currentLayer.push(new Date().getTime() * 10 + events, [mouseX, mouseY]);
        reDraw()
      }
      e.preventDefault();
    },
    release = function() {
      paint = false;
      if (currentLayer) {
        events = 0;
        reDraw();
      }
      currentLayer = null;
    },
    init = function(id, appendTo, width, height) {
      room = id;
      canvas = document.createElement('canvas');
      canvas.setAttribute('width', width);
      canvas.setAttribute('height', height);
      canvas.setAttribute('id', 'canvas');
      appendTo.appendChild(canvas);

      context = canvas.getContext("2d");

      canvas.addEventListener("mousedown", press, false);
      canvas.addEventListener("mousemove", drag, false);
      canvas.addEventListener("mouseup", release);
      canvas.addEventListener("mouseout", release, false);

      // Add touch event listeners to canvas element
      canvas.addEventListener("touchstart", press, false);
      canvas.addEventListener("touchmove", drag, false);
      canvas.addEventListener("touchend", release, false);
      canvas.addEventListener("touchcancel", release, false);

    }
  return {
    init: init
  }

})();
App.init('', document.body, 800, 800)