Отменить с проблемой обводки ластиком - PullRequest
0 голосов
/ 07 августа 2020

Я стираю рисунок холста 1 раз, тогда функция «Отменить» работает нормально, но когда я стираю более 1 раза, функция «Отменить» работает как обводка линии, она работает на последнем этапе стирания, но другие работают как обводка линии, пожалуйста, см. под кодом:

function Sketchpad(config) {
  // Enforces the context for all functions
  for (var key in this.constructor.prototype) {
    this[key] = this[key].bind(this);
  }

  // Warn the user if no DOM element was selected
  if (!config.hasOwnProperty('element')) {
    console.error('SKETCHPAD ERROR: No element selected');
    return;
  }

  this.element = config.element;

  // Width can be defined on the HTML or programatically
  this._width = config.width || $(this.element).attr('data-width') || 0;
  this._height = config.height || $(this.element).attr('data-height') || 0;

  // Pen attributes
  this.color = config.color || $(this.element).attr('data-color') || '#000000';
  this.penSize = config.penSize || $(this.element).attr('data-penSize') || 5;

  // ReadOnly sketchpads may not be modified
  this.readOnly = config.readOnly ||
                  $(this.element).attr('data-readOnly') ||
                  false;
  if (!this.readOnly) {
      $(this.element).css({cursor: 'crosshair'});
  }

  // Stroke control variables
  this.strokes = config.strokes || [];
  console.log(this.strokes)
  this._currentStroke = {
    color: null,
    size: null,
    lines: [],
  };

  // Undo History
  this.undoHistory = (!bErasing) ? (config.undoHistory || []) : [];

  // Animation function calls
  this.animateIds = [];

  // Set sketching state
  this._sketching = false;

  // Setup canvas sketching listeners
  this.reset();
}

//
// Private API
//

Sketchpad.prototype._cursorPosition = function(event) {
  return {
    x: event.pageX - $(this.canvas).offset().left,
    y: event.pageY - $(this.canvas).offset().top,
  };
};

Sketchpad.prototype._draw = function(start, end, color, size) {
  this._stroke(start, end, color, size, 'source-over');
};

Sketchpad.prototype._erase = function(start, end, color, size) {
  this._stroke(start, end, color, size, 'destination-out');
};

Sketchpad.prototype._stroke = function(start, end, color, size) {
  this.context.save();
  if(bErasing){
    this.context.globalCompositeOperation = "destination-out";
  }else{
    this.context.globalCompositeOperation = "source-over";
  }
    // if(size === 7 || size === 13){
    //   console.log(size)
    //   this.context.lineJoin = 'square';
    //   this.context.lineCap = 'square';
    // }
    // else{
      this.context.lineJoin = 'round';
      this.context.lineCap = 'round';
    // }
      this.context.strokeStyle = color;
      this.context.lineWidth = size;
    // switch(size){

    //     case 2:
    //     this.context.globalAlpha = 1;
    //     break;
    //     case 7:
    //     this.context.globalAlpha = 0.7;
    //     break;
    //     case 13:
    //     this.context.globalAlpha = 0.4;
    //     break;
    //     default:
    //     this.context.globalAlpha = 0.2;
    // }
    this.context.beginPath();
    this.context.moveTo(start.x, start.y);
    this.context.lineTo(end.x, end.y);
    this.context.closePath();
    this.context.stroke();

    this.context.restore();
};

//
// Callback Handlers
//

Sketchpad.prototype._mouseDown = function(event) {
  this._lastPosition = this._cursorPosition(event);
  this._currentStroke.color = this.color;
  this._currentStroke.size = this.penSize;
  this._currentStroke.lines = [];
  // console.log(this._currentStroke.lines)
  this._sketching = true;
  this.canvas.addEventListener('mousemove', this._mouseMove);
};

Sketchpad.prototype._mouseUp = function(event) {
  if (this._sketching) {
    this.strokes.push($.extend(true, {}, this._currentStroke));
    this._sketching = false;
  }
  this.canvas.removeEventListener('mousemove', this._mouseMove);
};

Sketchpad.prototype._mouseMove = function(event) {
  var currentPosition = this._cursorPosition(event);

  this._draw(this._lastPosition, currentPosition, this.color, this.penSize);
  this._currentStroke.lines.push({
    start: $.extend(true, {}, this._lastPosition),
    end: $.extend(true, {}, currentPosition),
  });

  this._lastPosition = currentPosition;
};

Sketchpad.prototype._touchStart = function(event) {
  event.preventDefault();
  if (this._sketching) {
    return;
  }
  this._lastPosition = this._cursorPosition(event.changedTouches[0]);
  this._currentStroke.color = this.color;
  this._currentStroke.size = this.penSize;
  this._currentStroke.lines = [];
  this._sketching = true;
  this.canvas.addEventListener('touchmove', this._touchMove, false);
};

Sketchpad.prototype._touchEnd = function(event) {
  event.preventDefault();
  if (this._sketching) {
    this.strokes.push($.extend(true, {}, this._currentStroke));
    this._sketching = false;
  }
  this.canvas.removeEventListener('touchmove', this._touchMove);
};

Sketchpad.prototype._touchCancel = function(event) {
  event.preventDefault();
  if (this._sketching) {
    this.strokes.push($.extend(true, {}, this._currentStroke));
    this._sketching = false;
  }
  this.canvas.removeEventListener('touchmove', this._touchMove);
};

Sketchpad.prototype._touchLeave = function(event) {
  event.preventDefault();
  if (this._sketching) {
    this.strokes.push($.extend(true, {}, this._currentStroke));
    this._sketching = false;
  }
  this.canvas.removeEventListener('touchmove', this._touchMove);
};

Sketchpad.prototype._touchMove = function(event) {
  event.preventDefault();
  var currentPosition = this._cursorPosition(event.changedTouches[0]);

  this._draw(this._lastPosition, currentPosition, this.color, this.penSize);
  this._currentStroke.lines.push({
    start: $.extend(true, {}, this._lastPosition),
    end: $.extend(true, {}, currentPosition),
  });

  this._lastPosition = currentPosition;
};

//
// Public API
//

Sketchpad.prototype.reset = function() {
  // Set attributes
  this.canvas = $(this.element)[0];
  this.canvas.width = this._width;
  this.canvas.height = this._height;
  this.context = this.canvas.getContext('2d');

  // Setup event listeners
  this.redraw(this.strokes);

  if (this.readOnly) {
    return;
  }

  // Mouse
  this.canvas.addEventListener('mousedown', this._mouseDown);
  this.canvas.addEventListener('mouseout', this._mouseUp);
  this.canvas.addEventListener('mouseup', this._mouseUp);

  // Touch
  this.canvas.addEventListener('touchstart', this._touchStart);
  this.canvas.addEventListener('touchend', this._touchEnd);
  this.canvas.addEventListener('touchcancel', this._touchCancel);
  this.canvas.addEventListener('touchleave', this._touchLeave);
};

Sketchpad.prototype.drawStroke = function(stroke) {
  for (var j = 0; j < stroke.lines.length; j++) {
    var line = stroke.lines[j];
    this._draw(line.start, line.end, stroke.color, stroke.size);
  }
};
Sketchpad.prototype.erase = function() {
  // this._erase(line.start, line.end, stroke.color, stroke.size);
};

Sketchpad.prototype.redraw = function(strokes) {
  for (var i = 0; i < strokes.length; i++) {
    this.drawStroke(strokes[i]);
  }
};

Sketchpad.prototype.toObject = function() {
  return {
    width: this.canvas.width,
    height: this.canvas.height,
    strokes: this.strokes,
    undoHistory: this.undoHistory,
  };
};

Sketchpad.prototype.toJSON = function() {
  return JSON.stringify(this.toObject());
};

Sketchpad.prototype.animate = function(ms, loop, loopDelay) {
  this.clear();
  var delay = ms;
  var callback = null;
  for (var i = 0; i < this.strokes.length; i++) {
    var stroke = this.strokes[i];
    for (var j = 0; j < stroke.lines.length; j++) {
      var line = stroke.lines[j];
      callback = this._draw.bind(this, line.start, line.end,
                                 stroke.color, stroke.size);
      this.animateIds.push(setTimeout(callback, delay));
      delay += ms;
    }
  }
  if (loop) {
    loopDelay = loopDelay || 0;
    callback = this.animate.bind(this, ms, loop, loopDelay);
    this.animateIds.push(setTimeout(callback, delay + loopDelay));
  }
};

Sketchpad.prototype.cancelAnimation = function() {
  for (var i = 0; i < this.animateIds.length; i++) {
    clearTimeout(this.animateIds[i]);
  }
};

Sketchpad.prototype.clear = function() {
  this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
};

Sketchpad.prototype.undo = function() {
  this.clear();
  var stroke = this.strokes.pop();
  if (stroke) {
    this.undoHistory.push(stroke);
    this.redraw(this.strokes);
  }
};

Sketchpad.prototype.redo = function() {
  var stroke = this.undoHistory.pop();
  if (stroke) {
    this.strokes.push(stroke);
    this.drawStroke(stroke);
  }
};

, а также возникла проблема при попытке изменить текстуру кистей в соответствии с размером пера.

ластик работает нормально, и отмена также работает нормально, Единственная проблема заключается в том, что когда мы стираем более одного раза, затем пытаемся отменить, тогда последнее стирание возвращается к реальному рисунку, но другие предыдущие работы, такие как обводка линии и отображение рисунка в соответствии с движением мыши ластика на холсте.

Это моя функция для вызова вышеуказанных методов:

     var x = "#CB7342",
        y = 2;
    var bErasing = false;
    var canvas, canvasWidth, canvasHeight;
    var ctx;
    var lastPt=null;
    var pathsry = [];
    var points = [];
    var state;
    var colour;
    // past states
    function ySize(size) {

        y = size;
        sketchpad.penSize = y;
    }

    var sketchpad;
    function undo(){
        bErasing = false;
        sketchpad.undo();
        if($('#erase').hasClass('active')){

            bErasing = true;
        }
    }

    function init() {
        canvas = document.getElementById('sheet');
        ctx = canvas.getContext('2d');
        var canvasOffset = $('#sheet').offset();
        var parent = canvas.parentNode;
        canvas.width = parent.clientWidth;
        canvas.height = parent.clientHeight;
        // alert(bErasing)
        sketchpad = new Sketchpad({
            element: '#sheet',
            width: canvas.width,
            height: canvas.height,
            color: null,
            penSize: 2,
            globalAlpha: 0.1
        });
    }
    $(document).on('click', "#erase", function () {
        bErasing = true;
    });
...