canvas отрисовка сохраненных координат

90
05 июля 2021, 21:40

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

Проблема 1: после отрисовки сохраненных координат фигура появившиеся на холсте исчезнет(сотрется), при первом нажатии мыши, если пользователь продолжит рисовать рядом с отрисовавшейся фигурой полигон. Этого быть не должно. Это происходит из-за установки от чистки canvas при перерисовки координат.

Проблема 2: если я убираю от чистку проблема 1 решается, но фигуры перестают быть прозрачными в процессе рисования и закрашивают полностью участок холста.

Как решить? пожалуйста объясните как это работает и как это исправить.

<!DOCTYPE html> 
<html lang="ru"> 
<head> 
 
    <meta charset="UTF-8"> 
    <title>Streaming</title> 
    <meta name="viewport" content="width=device-width, initial-scale=1"> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}"> 
 
</head> 
 
<body> 
 
    <h1></h1> 
 
    <div class="main_cont"> 
 
 
 
        <img class="img-1" src="{{ url_for('video_feed') }}"> 
        <canvas id='canvas' height='500' width='500' style="border:1px solid red;"></canvas> 
 
        <input type = "button" id = "clear" name = "clear" value = "Очистить холст" /> 
        <button id = "clearButton">Очистить input</button> 
        <button id = "addButton">Показать координаты</button> 
        <button id = "repainButton">Отрисовать сохранившиеся</button> 
        <button id = "saveCoord">Сохранить координаты</button> 
 
        <form action="" method="post" target="_blank"> 
        <p> 
            <label class="rect_coord" for="coordinates">Coordinates camera</label><br> 
            <input type="text" id="rect_coord" name="coordinates" required><br> 
        </p> 
        <p> 
            <input class="button2" style='margin-top:20px;' type="submit" name="Save" > 
        </p> 
 
        </form> 
 
 
    </div> 
    <script type="text/javascript"> 
 
 
//====================================================================================================== 
        let can = document.getElementById('canvas'); 
                can.width = 500; 
                can.height = 500; 
                let x, y; 
                let ctx = can.getContext('2d'); //Выбрать пространство 
                let pts = [[]]; 
                let coordinats; 
                let new_array = []; 
                let upcomingFigure = []; 
                let data; 
                var clearCoordinat; 
//====================================================================================================== 
                // убирает выделение холста синим цветом при двойном нажатии мыши 
                document.getElementById('canvas'); 
                canvas.onselectstart = function () { return false; } 
//====================================================================================================== 
                // отрисовывает сохраненные координаты фигур 
                document.getElementById('repainButton').addEventListener('click', function(event) { 
                    // извлекаем данные из localstorege 
                    data = JSON.parse(window.localStorage.getItem('storeObj')); 
                    // data[data.length-1].pop(); //удалим повторную точку 
                    console.info('ЭТО data', data) 
                    data.push([]) // новая коллекция точек 
                    repaintButton(); // вызываев функцию для отрисовки с кнопки 
 
 
                    document.getElementById('clear').addEventListener('click', function() { 
                        ctx.clearRect(0, 0, canvas.width, canvas.height); 
                      }); 
                  },false) 
//====================================================================================================== 
                // замыкаение и отрисовка фигуры по двойному клику вызовом func(repaint) 
                $( "#canvas" ).dblclick(function() { 
                  pts[pts.length-1].pop(); //удалим повторную точку 
                  pts.push([]) // новая коллекция точек 
                  repaint(); 
                  coordinats = pts 
//====================================================================================================== 
                // добавление в input координат в строке JSON 
                  remove_empty_str = function(coordinats) { 
                              new_array = []; 
 
                              console.log(new_array) 
                              for (ii = 0, len = coordinats.length; ii < len; ii++) { 
                                item = coordinats[ii]; 
                                if (item !== "" || item !== null || item !== 0) { 
                                  new_array.push(item); 
                              }; 
                                if (new_array.length > 2 || new_array[0].length === 1){ 
                                  upcomingFigure = new_array.splice(0, 1); 
                                   if (upcomingFigure[0].lenght === 1) { 
                                    upcomingFigure.splice(0, 1) 
                                }; 
 
                              }; 
                            } 
                              return new_array; 
                              return upcomingFigure; 
                            }; 
                              newIDs = remove_empty_str(coordinats); 
                                clearCoordinat = pts; 
                              document.getElementById('saveCoord').onclick = function(event) { 
                                window.localStorage.setItem('storeObj', JSON.stringify(clearCoordinat)); 
                              } 
 
                              let res = Array.from(new Set(new_array.flat())); 
 
                              document.getElementById('addButton').onclick = function(event) { 
                                if (res.length !==1 || res[0].length !== 2){ 
                                  document.getElementById('rect_coord').value = JSON.stringify(res)// поле заполнения координатами 
 
 
                                  // JSON.parse(window.localStorage.getItem('storeObj')); 
 
                                  return coordinats 
                              }; 
                            } 
 
 
                             // отчистка поля input с кнопки 
                              document.getElementById('clearButton').onclick = function(event) { 
                                document.getElementById("rect_coord").value = null; 
                                window.localStorage.removeItem('storeObj'); 
                            } 
 
                }); 
//======================================================================================================= 
                // события нажатия мыши и добавления координат в массив 
                can.addEventListener('mousedown', function(e){ 
                  pts[pts.length-1].push([ 
                    e.pageX - e.target.offsetLeft, 
                    e.pageY - e.target.offsetTop 
                  ]); 
                  repaint(); 
                [e.pageX - e.target.offsetLeft, e.pageY - e.target.offsetTop] 
 
                }); 
//======================================================================================================= 
                // перерисовка холста и отрисовка фигуры по точкам из массива 
                function repaint(){ 
                  if (repaintButton){ 
                  ctx.clearRect(0,0,can.width,can.height) 
                } 
                  ctx.strokeStyle = 'red'; 
                  ctx.globalAlpha = 0.5; // прозрачность 
                  ctx.fillStyle = 'red' //Цвет 
                  ctx.lineWidth = 5;//Толщина линий 
                  ctx.lineJoin = "miter"; // закругленность соединений линий 
 
                  // рисуем фигуры 
                    pts.forEach((shape, j)=> { 
                    ctx.beginPath(); 
                    shape.forEach((p, i) => { 
                      ctx[i ? 'lineTo' : 'moveTo'](...p); 
 
                    }) 
                    if(j !== pts.length-1){ 
                      ctx.fill(); 
                      ctx.closePath(); 
                    } 
                    ctx.stroke(); 
                  }) 
 
                  // рисуем синие точки только для последней фигуры 
                  pts[pts.length-1].forEach((p, i) => { 
                    ctx.strokeStyle = 'blue'; 
                    ctx.beginPath(); 
                    ctx.arc(...p, 10 / 20 ,0, Math.PI * 2);  //Круг 
                    ctx.stroke(); 
 
                  }) 
 
                  // кнопка очистки canvas 
                  document.getElementById('clear').addEventListener('click', function() { 
                        ctx.clearRect(0, 0, canvas.width, canvas.height); 
 
                        return pts = [[]];// отчищаю массив с точками для отрисовки фигуры 
                }, false) 
            } 
//====================================================================================================== 
              // получаем асинхронный запрос к локальному файлу file.json 
              function readTextFile(path_to_file, callback) { 
                  let rawFile = new XMLHttpRequest(); 
                  rawFile.overrideMimeType("application/json"); 
                  rawFile.open("GET", path_to_file, true); 
                  rawFile.onreadystatechange = function() { 
                      if (rawFile.readyState === 4 && rawFile.status == "200") { 
                          callback(rawFile.responseText); 
                      } 
                  } 
                  rawFile.send(null); 
              } 
 
              //usage: 
              readTextFile("http://localhost:5000/static/json/coord.json", function(text){ 
                  var file_data = JSON.parse(text); 
                  console.log(file_data); 
              }); 
 
//====================================================================================================== 
              // функция для отрисовки из сохраненых координат в фаиле file.json 
              function repaintButton(){ 
                  // ctx.clearRect(0,0,can.width,can.height); 
 
                  ctx.strokeStyle = 'red'; 
                  ctx.globalAlpha = 0.5; // прозрачность 
                  ctx.fillStyle = 'red' //Цвет 
                  ctx.lineWidth = 5;//Толщина линий 
                  ctx.lineJoin = "miter"; // закругленность соединений линий 
 
                  // рисуем фигуры 
                    data.forEach((shape, j)=> { 
                    ctx.beginPath(); 
                    shape.forEach((p, i) => { 
                      ctx[i ? 'lineTo' : 'moveTo'](...p); 
 
                    }) 
                    if(j !== data.length-1){ 
                      ctx.fill(); 
                      ctx.closePath(); 
                    } 
                    ctx.stroke(); 
                  }) 
 
                  // рисуем синие точки только для последней фигуры 
                  data[data.length-1].forEach((p, i) => { 
                    ctx.strokeStyle = 'blue'; 
                    ctx.beginPath(); 
                    ctx.arc(...p, 10 / 20 ,0, Math.PI * 2);  //Круг 
                    ctx.stroke(); 
 
                  }) 
                } 
//======================================================================================================= 
 
 
    </script> 
 
 
 
<script type="text/javascript" src="{{ url_for('static', filename='json/coord.json') }}"></script> 
<script src="{{ url_for('static', filename='js/script.js') }}"></script> 
</body> 
</html>

Answer 1

При восстановлении из localstorage необходимо заменить массив фигур которые сейчас рисуются (переменная pts) на тот который считан:

    pts = data;  /// я изменил одну эту строчку (№69)

<!DOCTYPE html> 
<html lang="ru"> 
<head> 
 
    <meta charset="UTF-8"> 
    <title>Streaming</title> 
    <meta name="viewport" content="width=device-width, initial-scale=1"> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}"> 
 
</head> 
 
<body> 
 
<h1></h1> 
 
<div class="main_cont"> 
 
 
 
    <img class="img-1" src="{{ url_for('video_feed') }}"> 
    <canvas id='canvas' height='500' width='500' style="border:1px solid red;"></canvas> 
 
    <input type = "button" id = "clear" name = "clear" value = "Очистить холст" /> 
    <button id = "clearButton">Очистить input</button> 
    <button id = "addButton">Показать координаты</button> 
    <button id = "repainButton">Отрисовать сохранившиеся</button> 
    <button id = "saveCoord">Сохранить координаты</button> 
 
    <form action="" method="post" target="_blank"> 
        <p> 
            <label class="rect_coord" for="coordinates">Coordinates camera</label><br> 
            <input type="text" id="rect_coord" name="coordinates" required><br> 
        </p> 
        <p> 
            <input class="button2" style='margin-top:20px;' type="submit" name="Save" > 
        </p> 
 
    </form> 
 
 
</div> 
<script type="text/javascript"> 
 
 
    //====================================================================================================== 
    let can = document.getElementById('canvas'); 
    can.width = 500; 
    can.height = 500; 
    let x, y; 
    let ctx = can.getContext('2d'); //Выбрать пространство 
    let pts = [[]]; 
    let coordinats; 
    let new_array = []; 
    let upcomingFigure = []; 
    let data; 
    var clearCoordinat; 
    //====================================================================================================== 
    // убирает выделение холста синим цветом при двойном нажатии мыши 
    document.getElementById('canvas'); 
    canvas.onselectstart = function () { return false; } 
    //====================================================================================================== 
    // отрисовывает сохраненные координаты фигур 
    document.getElementById('repainButton').addEventListener('click', function(event) { 
        // извлекаем данные из localstorege 
        data = JSON.parse(window.localStorage.getItem('storeObj')); 
        // data[data.length-1].pop(); //удалим повторную точку 
        console.info('ЭТО data', data) 
        pts = data // новая коллекция точек /// я изменил одну эту строчку 
        repaintButton(); // вызываев функцию для отрисовки с кнопки 
 
 
        document.getElementById('clear').addEventListener('click', function() { 
            ctx.clearRect(0, 0, canvas.width, canvas.height); 
        }); 
    },false) 
    //====================================================================================================== 
    // замыкаение и отрисовка фигуры по двойному клику вызовом func(repaint) 
    $( "#canvas" ).dblclick(function() { 
        pts[pts.length-1].pop(); //удалим повторную точку 
        pts.push([]) // новая коллекция точек 
        repaint(); 
        coordinats = pts 
//====================================================================================================== 
        // добавление в input координат в строке JSON 
        remove_empty_str = function(coordinats) { 
            new_array = []; 
 
            console.log(new_array) 
            for (ii = 0, len = coordinats.length; ii < len; ii++) { 
                item = coordinats[ii]; 
                if (item !== "" || item !== null || item !== 0) { 
                    new_array.push(item); 
                }; 
                if (new_array.length > 2 || new_array[0].length === 1){ 
                    upcomingFigure = new_array.splice(0, 1); 
                    if (upcomingFigure[0].lenght === 1) { 
                        upcomingFigure.splice(0, 1) 
                    }; 
 
                }; 
            } 
            return new_array; 
            return upcomingFigure; 
        }; 
        newIDs = remove_empty_str(coordinats); 
        clearCoordinat = pts; 
        document.getElementById('saveCoord').onclick = function(event) { 
            window.localStorage.setItem('storeObj', JSON.stringify(clearCoordinat)); 
        } 
 
        let res = Array.from(new Set(new_array.flat())); 
 
        document.getElementById('addButton').onclick = function(event) { 
            if (res.length !==1 || res[0].length !== 2){ 
                document.getElementById('rect_coord').value = JSON.stringify(res)// поле заполнения координатами 
 
 
                // JSON.parse(window.localStorage.getItem('storeObj')); 
 
                return coordinats 
            }; 
        } 
 
 
        // отчистка поля input с кнопки 
        document.getElementById('clearButton').onclick = function(event) { 
            document.getElementById("rect_coord").value = null; 
            window.localStorage.removeItem('storeObj'); 
        } 
 
    }); 
    //======================================================================================================= 
    // события нажатия мыши и добавления координат в массив 
    can.addEventListener('mousedown', function(e){ 
        pts[pts.length-1].push([ 
            e.pageX - e.target.offsetLeft, 
            e.pageY - e.target.offsetTop 
        ]); 
        repaint(); 
        [e.pageX - e.target.offsetLeft, e.pageY - e.target.offsetTop] 
 
    }); 
    //======================================================================================================= 
    // перерисовка холста и отрисовка фигуры по точкам из массива 
    function repaint(){ 
        if (repaintButton){ 
            ctx.clearRect(0,0,can.width,can.height) 
        } 
        ctx.strokeStyle = 'red'; 
        ctx.globalAlpha = 0.5; // прозрачность 
        ctx.fillStyle = 'red' //Цвет 
        ctx.lineWidth = 5;//Толщина линий 
        ctx.lineJoin = "miter"; // закругленность соединений линий 
 
        // рисуем фигуры 
        pts.forEach((shape, j)=> { 
            ctx.beginPath(); 
            shape.forEach((p, i) => { 
                ctx[i ? 'lineTo' : 'moveTo'](...p); 
 
            }) 
            if(j !== pts.length-1){ 
                ctx.fill(); 
                ctx.closePath(); 
            } 
            ctx.stroke(); 
        }) 
 
        // рисуем синие точки только для последней фигуры 
        pts[pts.length-1].forEach((p, i) => { 
            ctx.strokeStyle = 'blue'; 
            ctx.beginPath(); 
            ctx.arc(...p, 10 / 20 ,0, Math.PI * 2);  //Круг 
            ctx.stroke(); 
 
        }) 
 
        // кнопка очистки canvas 
        document.getElementById('clear').addEventListener('click', function() { 
            ctx.clearRect(0, 0, canvas.width, canvas.height); 
 
            return pts = [[]];// отчищаю массив с точками для отрисовки фигуры 
        }, false) 
    } 
    //====================================================================================================== 
    // получаем асинхронный запрос к локальному файлу file.json 
    function readTextFile(path_to_file, callback) { 
        let rawFile = new XMLHttpRequest(); 
        rawFile.overrideMimeType("application/json"); 
        rawFile.open("GET", path_to_file, true); 
        rawFile.onreadystatechange = function() { 
            if (rawFile.readyState === 4 && rawFile.status == "200") { 
                callback(rawFile.responseText); 
            } 
        } 
        rawFile.send(null); 
    } 
 
    //usage: 
    readTextFile("http://localhost:5000/static/json/coord.json", function(text){ 
        var file_data = JSON.parse(text); 
        console.log(file_data); 
    }); 
 
    //====================================================================================================== 
    // функция для отрисовки из сохраненых координат в фаиле file.json 
    function repaintButton(){ 
        // ctx.clearRect(0,0,can.width,can.height); 
 
        ctx.strokeStyle = 'red'; 
        ctx.globalAlpha = 0.5; // прозрачность 
        ctx.fillStyle = 'red' //Цвет 
        ctx.lineWidth = 5;//Толщина линий 
        ctx.lineJoin = "miter"; // закругленность соединений линий 
 
        // рисуем фигуры 
        data.forEach((shape, j)=> { 
            ctx.beginPath(); 
            shape.forEach((p, i) => { 
                ctx[i ? 'lineTo' : 'moveTo'](...p); 
 
            }) 
            if(j !== data.length-1){ 
                ctx.fill(); 
                ctx.closePath(); 
            } 
            ctx.stroke(); 
        }) 
 
        // рисуем синие точки только для последней фигуры 
        data[data.length-1].forEach((p, i) => { 
            ctx.strokeStyle = 'blue'; 
            ctx.beginPath(); 
            ctx.arc(...p, 10 / 20 ,0, Math.PI * 2);  //Круг 
            ctx.stroke(); 
 
        }) 
    } 
    //======================================================================================================= 
 
 
</script> 
 
 
 
<script type="text/javascript" src="{{ url_for('static', filename='json/coord.json') }}"></script> 
<script src="{{ url_for('static', filename='js/script.js') }}"></script> 
</body> 
</html>

READ ALSO
Как сделать анимацию эффект рандома?

Как сделать анимацию эффект рандома?

Как сделать анимацию? Надо прокрутить картинки 3 разаА затем остановить на выбранной

98
Как реализовать вывод текста из button в input?

Как реализовать вывод текста из button в input?

При нажатии на кнопку должен выводиться текст из нее в inputНичего подобного не нашла, как это реализовать?

65
Библиотеки, оптимизация и соглашения о вызове

Библиотеки, оптимизация и соглашения о вызове

Для примера рассмотрим винду

81