рисование мышью canvas

93
16 мая 2021, 01:00

Есть проблема при рисовании юзером 4 угольной формы на canvas, когда ведешь мышью рисуется форма stroke и она очищается методом clearRect, но когда начинаешь вести во внутрь этого же 4 угольника он перестает его чистить и оставляет внутри черные линии, когда ведешь опять в том направлении он опять очищает внутреннее пространство.Мне нужно чтобы новые квадраты не отрисовывались и при нажатии мыши не удалялся первый и единственный 4-х угольник. Как мне правильно передать чтобы , пользователь рисовал только 1 квадрат нужных ему размеров и мог отчистить canvas только с помощью кнопки "отчистить" ? Может сказано запутано, но это так!

  1. Почему это происходит?

  2. Как это исправить?

вот весь код:

if (window.addEventListener) { 
  window.addEventListener('load', function() { 
 
    var canvas, context, tool; 
 
    function init() { 
      // Находим canvas элемент 
      canvas = document.getElementById('tablet'); 
 
 
 
      if (!canvas) { 
        alert('Ошибка! Canvas элемент не найден!'); 
        return; 
      } 
 
      if (!canvas.getContext) { 
        alert('Ошибка: canvas.getContext не существует!'); 
        return; 
      } 
 
      // Получаем 2D canvas context. 
      context = canvas.getContext('2d'); 
      context.strockeStyle = '#4caf50'; 
      if (!context) { 
        alert('Ошибка: getContext! не существует'); 
        return; 
      } 
      // 
      tool = new tool_rect(); 
      canvas.addEventListener('mousedown', ev_canvas, false); 
      canvas.addEventListener('mousemove', ev_canvas, false); 
      canvas.addEventListener('mouseup', ev_canvas, false); 
    } 
 
    // Здесь мы будем ловить движения мыши и отрисовывать прямоугольньник 
    function tool_rect() { 
      var tool = this; 
      this.started = false; 
 
 
      this.mousedown = function(ev) { 
 
        tool.started = true; 
        tool.x0 = ev._x; 
        tool.y0 = ev._y; 
      }; 
 
      this.mousemove = function(ev) { 
        if (!tool.started) { 
          return; 
        } 
        // высчитываем прямоугольник по зажатой мышки и координаты при ее ведении по холсту 
        var x = Math.min(ev._x, tool.x0), 
          y = Math.min(ev._y, tool.y0), 
          w = Math.abs(ev._x - tool.x0), 
          h = Math.abs(ev._y - tool.y0); 
 
 
 
 
 
        context.clearRect(x, y, w, h); // стирает старый прямоугольник при попытки создать новый 
 
        document.getElementById('clear').addEventListener('click', function() { 
          context.clearRect(0, 0, canvas.width, canvas.height); 
        }, false) 
 
 
        if (!w || !h) { 
          return; 
 
 
        } 
 
        context.strokeRect(x, y, w, h); // создание прямоугольника без заливки согласно переданным параметром от мышки 
 
      }; 
 
 
      this.mouseup = function(ev) { 
        if (tool.started) { 
          tool.mousemove(ev); 
          tool.started = false; 
 
 
        } 
      }; 
    } 
 
    // Эта функция определяет позицию курсора относительно холста 
    function ev_canvas(ev) { 
      if (ev.layerX || ev.layerX == 0) { // Firefox 
        ev._x = ev.layerX; 
        ev._y = ev.layerY; 
      } else if (ev.offsetX || ev.offsetX == 0) { // Opera 
        ev._x = ev.offsetX; 
        ev._y = ev.offsetY; 
      } 
 
      // Вызываем обработчик события tool 
      var func = tool[ev.type]; 
      if (func) { 
        func(ev); 
      } 
    } 
 
    init(); 
 
  }, false); 
}
#canvas { 
  width: 100px; 
  height: 150px; 
  border: 1px solid red; 
  position: relative; 
  display: flex; 
} 
 
.rectangle { 
  border: 1px solid #FF0000; 
  position: absolute; 
}
<h1 style="text-align: center;">Video Streaming</h1> 
 
<div style="display:flex; margin:0 45%"> 
 
  <img src="{{ url_for('video_feed') }}"> 
  <img style="" src="{{ url_for('video_feed2') }}"> 
 
  <canvas id='tablet' height='150' width='100' style=" 
                    border: 1px solid red; 
                    position: relative; 
                    right: 101px;"> 
        </canvas> 
  <input type="button" id="clear" name="clear" value="Очистить" /> 
</div>

Answer 1

Вы очищаете кусочек канвы, меньше чем прямоугольник, очищайте всю канву:

 // стирает старый прямоугольник при попытки создать новый
 context.clearRect(0, 0, canvas.width, canvas.height); 

UPD: судя по тому что я понял из вопроса добавил еще один флаг в код. tool.deactivated, который устанавливается когда нарисован прямоугольник и сбрасывается по кнопке очистить. так же слушатель на mouseup я повесил не на канву а на документ, чтобы отлавливать завершение рисования вне канвы.

if (window.addEventListener) { 
  window.addEventListener('load', function() { 
 
    var canvas, context, tool; 
 
    function init() { 
      // Находим canvas элемент 
      canvas = document.getElementById('tablet'); 
 
      if (!canvas) { 
        alert('Ошибка! Canvas элемент не найден!'); 
        return; 
      } 
 
      if (!canvas.getContext) { 
        alert('Ошибка: canvas.getContext не существует!'); 
        return; 
      } 
 
      // Получаем 2D canvas context. 
      context = canvas.getContext('2d'); 
      context.strokeStyle = '#4caf50'; 
      if (!context) { 
        alert('Ошибка: getContext! не существует'); 
        return; 
      } 
      // 
      tool = new tool_rect(); 
      canvas.addEventListener('mousedown', ev_canvas, false); 
      canvas.addEventListener('mousemove', ev_canvas, false); 
      addEventListener('mouseup', ev_canvas, false); 
    } 
 
    // Здесь мы будем ловить движения мыши и отрисовывать прямоугольньник 
    function tool_rect() { 
      var tool = this; 
      this.started = false; 
 
      this.mousedown = function(ev) { 
        if (tool.deactivated)  
          return; 
        tool.started = true; 
        tool.x0 = ev._x; 
        tool.y0 = ev._y; 
      }; 
 
      this.mousemove = function(ev) { 
        if (!tool.started || tool.deactivated) { 
          return; 
        } 
        // высчитываем прямоугольник по зажатой мышки и координаты при ее ведении по холсту 
        var x = Math.min(ev._x, tool.x0), 
          y = Math.min(ev._y, tool.y0), 
          w = Math.abs(ev._x - tool.x0), 
          h = Math.abs(ev._y - tool.y0); 
 
        context.clearRect(0, 0, canvas.width, canvas.height); // стирает старый прямоугольник при попытки создать новый 
 
        document.getElementById('clear').addEventListener('click', function() { 
          context.clearRect(0, 0, canvas.width, canvas.height); 
          tool.deactivated = false; 
          clear.setAttribute('disabled', 'true') 
        }, false) 
 
 
        if (!w || !h) { 
          return; 
        } 
 
        context.strokeRect(x, y, w, h); // создание прямоугольника без заливки согласно переданным параметром от мышки 
      }; 
 
      this.mouseup = function(ev) { 
        if (tool.started) { 
          tool.started = false; 
          tool.deactivated = true; 
          clear.disabled = false; 
        } 
      }; 
    } 
 
    // Эта функция определяет позицию курсора относительно холста 
    function ev_canvas(ev) { 
      if (ev.layerX || ev.layerX == 0) { // Firefox 
        ev._x = ev.layerX; 
        ev._y = ev.layerY; 
      } else if (ev.offsetX || ev.offsetX == 0) { // Opera 
        ev._x = ev.offsetX; 
        ev._y = ev.offsetY; 
      } 
 
      // Вызываем обработчик события tool 
      var func = tool[ev.type]; 
      if (func) { 
        func(ev); 
      } 
    } 
 
    init(); 
 
  }, false); 
}
#canvas { 
  width: 100px; 
  height: 150px; 
  border: 1px solid red; 
  position: relative; 
  display: flex; 
} 
 
.rectangle { 
  border: 1px solid #FF0000; 
  position: absolute; 
}
<h1 style="text-align: center;">Video Streaming</h1> 
<div style="display:flex; margin:0 45%"> 
  <canvas id='tablet' height='150' width='100' style="border: 1px solid red;position: relative;right: 101px;"></canvas> 
  <input type="button" id="clear" name="clear" value="Очистить" disabled/> 
</div>

READ ALSO
Failed to load resource: the server responded with a status of 404 (Not Found), как исправить?

Failed to load resource: the server responded with a status of 404 (Not Found), как исправить?

Учу ajax, и столкнулся вот с такой ошибкой:

155
не работает обработчик событий onClick

не работает обработчик событий onClick

не работает обработчик событий в дочернем элементе в реакте onClick при клике на элементе из списка ничего не происходит

74
Почему при импорте файла scss, в другой scss, он не хочет его читать или не видит?

Почему при импорте файла scss, в другой scss, он не хочет его читать или не видит?

При импорте файла scss, в другой scss, он не хочет его читать, или не видит?

101