Есть задача позволить пользователю выборочно выделять и удалять полигоны которые он рисует. Проблема 1: как выделить нужный полигон из возможного множества полигонов нарисованных пользователем. Проблема 2: как сделать чтобы когда нужно выделить полигон при клике на полигон не оставалась точка координат и не добавлялись данные в массив с координатами. Проблема 3: при выделении полигона это должно быть видно(изменение strokestyle или fillstyle). Пожалуйста объясните как реализовать задуманное, предложите варианты. Спасибо!
<!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="style.css">
</head>
<body>
<p style="color: #dddddd; margin-left:30px;">
X:<span id="offsetX"></span>
Y:<span id="offsetY"></span>
</p>
<div class="main_cont">
<canvas id='canvas' height='500' width='500' style="border:1px solid red;"></canvas>
<dialog id='dialog'>
<p id='p_dialog'></p>
<button id="closeWindow">Закрыть</button>
</dialog>
<div id="button_container">
<button id = "clearCanvas">Clear canvas</button>
<button id="showCoord">Show coord</button>
<button id = "clearSaveCoord">Clear save coord</button>
<button id = "repainButton">Load</button>
<button id = "saveCoord">Save</button>
<button id = "back">Back one point</button>
<button id = "readCoord">Read Coord</button>
<form action="" method="post" target="_blank">
<p>
<input type="hidden" id="rect_coord" name="coordinates" required><br>
</p>
<p>
<input class="button2" style='margin-top:20px;' type="submit" name="Save" title="">
</p>
</form>
</div>
<dialog id='dialogRedCoord'>
<div id="add" style="display:grid;">
<button id="addInput">+</button>
</div>
<button id="closeWindowReadCoord">Закрыть</button>
<button id="addDataFromInput">Пременить</button>
</dialog>
</div>
<script type="text/javascript">
//======================================================================================================
let can = document.getElementById('canvas');// холст
can.width = 500; // ширина холста
can.height = 500; // высота холста
let ctx = can.getContext('2d'); // выбрать пространство
let pts = [[]]; // массив с точками координат
let data = null; // массив координат из localStorage
let clearCoordinat; // сохраненые данные в localStorage
let x, y;
//======================================================================================================
// выводим отображение координат(offset) на холсте при ведении мыши
document.getElementById('canvas').onmousemove = function(event){
event = event || window.event;
document.getElementById('offsetX').innerHTML = event.offsetX;
document.getElementById('offsetY').innerHTML = event.offsetY;
};
//======================================================================================================
// убирает выделение холста синим цветом при двойном нажатии мыши
document.getElementById('canvas');
canvas.onselectstart = function () { return false; };
//======================================================================================================
// отрисовывает сохраненные координаты фигур
document.getElementById('repainButton').addEventListener('click', function(event) {
data = JSON.parse(window.localStorage.getItem('storeObj'));
// извлекаем данные из localstorege
if (data === null){
return alert('Нет сохраненых объектов');
} else{
console.info('ЭТО data', data)
pts = data // новая коллекция точек /// я изменил одну эту строчку
repaintButton(); // вызываев функцию для отрисовки с кнопки
}
document.getElementById('clearCanvas').addEventListener('click', function() {
ctx.clearRect(0, 0, can.width, can.height);
});
},false);
//=======================================================================================================
// шаг назад по нажатию кнопки при раставлении точек
document.getElementById('back').addEventListener('click', function(event) {
pts[pts.length-1].pop()
repaint();
},false);
//======================================================================================================
// замыкаение и отрисовка фигуры по двойному клику вызовом func(repaint) (JQUERY)
$( "#canvas" ).dblclick(function() {
pts[pts.length-1].pop(); // удалим повторную точку
pts.push([]) // новая коллекция точек
repaint(); // вызываем функцию отрисовки
//-------------------------------------------------------------------------------------------------------
// сохранение фигур в localStorage
clearCoordinat = pts;
document.getElementById('saveCoord').onclick = function(event) {
if (clearCoordinat === null){
alert('Нет данных для сохранения')
} else {
window.localStorage.setItem('storeObj', JSON.stringify(clearCoordinat));
alert('Сохранено')
};
};
});
//========================================================================================================
// обработка массива с сохранеными точками в localStorage для отображения координат
document.getElementById('showCoord').onclick = function(event) {
let showCoord = JSON.parse(window.localStorage.getItem('storeObj'))
if(showCoord !== null){
let prop = Object.values(showCoord)
for (let i in prop){
for (let j in prop[i]){
for(let v in prop[i][j]){
if(v%2==0){
prop[i][j][v] = ' x: ' + prop[i][j][v]
} else {
prop[i][j][v] = ' y: ' + prop[i][j][v]
};
};
};
};
//--------------------------------------------------------------------------------------------------------
// делаем из масива словарь в формате json и придаем красивый вид
showCoord = JSON.stringify(Object.assign({}, showCoord), null, 4)
console.info(showCoord)
//--------------------------------------------------------------------------------------------------------
// вывод обработаных данных в сплывающее окно
document.getElementById('p_dialog').innerText = 'Координаты: ' + showCoord // заполнение координатами
//-------------------------------------------------------------------------------------------------------
// всплывающее окно с сохраненными координатами
let dialog = document.querySelector('dialog');
dialog.show();
document.querySelector('#closeWindow').onclick = function() {
dialog.close();
};
} else{
alert('Нет сохраненых координат для отображения')
};
};
//=========================================================================================================
// отчистка поля input с кнопки и удаление сохраненых координат из localStorage
document.getElementById('clearSaveCoord').onclick = function(event) {
if (clearCoordinat !== null){
let delCoord = confirm("Вы уверены что хотите отчистить все? Это также приведет к удалению сохраненых координат.");
if (delCoord){
dialog.close();
document.getElementById("rect_coord").value = null;
window.localStorage.removeItem('storeObj');
return clearCoordinat = null;
};
} else {
alert('Нет сохраненных данных для удаления')
};
};
//=======================================================================================================
// события нажатия мыши и добавления координат в массив
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]
});
//=======================================================================================================
// функция рисования и обновления точек на холсте по точкам из массива pts
function repaint(){
ctx.clearRect(0,0,can.width,can.height)
ctx.strokeStyle = '#00f';
ctx.fillStyle = 'rgba(255, 255, 253, 0.5)' // Цвет
ctx.lineWidth = 3; // Толщина линий
ctx.lineJoin = "miter"; // Закругленность соединений линий
// ***рисуем фигуры***
// shape = фигура
// j = номер фигуры
// p = точка. выражена как значение двух координат x, y в массиве по 2 элемента
// i = index массива
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 = '#000';
ctx.fillStyle = 'rgba(255, 255, 253, 0.5)'
ctx.beginPath();
ctx.arc(...p, 3.6 / 1.4 ,0, Math.PI * 2); //Круг
// ctx.rect(...p, 6, 6)
ctx.stroke();
})
//-----------------------------------------------------------------------------------------------------
// кнопка очистки canvas
document.getElementById('clearCanvas').addEventListener('click', function() {
ctx.clearRect(0, 0, can.width, can.height);
return pts = [[]];// отчищаю массив с точками для отрисовки фигуры
}, false)
};
//======================================================================================================
// функция асинхронный запрос к локальному файлу на сервере coord.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);
};
//=======================================================================================================
// получаем фаил
readTextFile("http://localhost:5000/static/json/coord.json", function(text){
let file_data = JSON.parse(text);
});
//======================================================================================================
// функция для отрисовки из сохраненых координат в localStorage
function repaintButton(){
ctx.clearRect(0,0,can.width,can.height);
ctx.strokeStyle = '#00f';
ctx.fillStyle = 'rgba(255, 255, 253, 0.5)' // Цвет
ctx.lineWidth = 3; // Толщина линий
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();
})
};
//======================================================================================================
// создаю всплывающее окно с динамическим добавлением элементов input для ввода координат
document.getElementById('readCoord').addEventListener('click', function(event) {
let dialogReadCoord = document.getElementById('dialogRedCoord');
dialogReadCoord.show();
addElementInput
document.querySelector('#closeWindowReadCoord').onclick = function() {
dialogReadCoord.close();
};
});
//=====================================================================================================
// функция динамического создания, добавления в DOM и удаления элементов input (JQUERY)
let addElementInput = $(document).ready(function () {
let max_fields = 1000;
let wrapper = $("#add");
let add_button = $("#addInput");
let x = 1;
$(add_button).click(function(e){
e.preventDefault();
if(x < max_fields){
x++;
$(wrapper).append('<div><span>X:</span><input class="input_coord" type="" name=""><span>Y:</span><input class="input_coord" type="" name=""><button class="delete">Delete</button></div>'); //add input box
} else{
alert('You Reached the limits')
}
});
$(wrapper).on("click",".delete", function(e){
e.preventDefault(); $(this).parent('div').remove(); x--;
})
});
//=====================================================================================================
document.getElementById('addDataFromInput').addEventListener('click', function(event) {
let coordFromInput = [[]];
let text = document.getElementsByClassName("input_coord");
coordFromInput = coordFromInput.push(text);
console.log(typeof coordFromInput);
});
//======================================================================================================
// pts = this.pts;
// функция отслеживания состояния canvas
let mouse = {
x: 0,
y: 0,
};
let selected = false;
let Poligon = function(...points) {
this.points = pts
}
Poligon.prototype = {
draw() {
this.points.forEach((shape, j)=> {
ctx.beginPath();
shape.forEach((p, i) => {
ctx[i ? 'lineTo' : 'moveTo'](...p);
})
if(j !== this.points.length-1){
ctx.fill();
ctx.closePath();
}
ctx.stroke();
})
},
mouseIn() {
return PointInPoligon(mouse, ...this.points)
}
};
let shapes = [
new Poligon(
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();
})
),
]
shapes.forEach(n => n.draw())
window.onmousemove = function(e) {
mouse.x = e.pageX - can.offsetLeft;
mouse.y = e.pageY - can.offsetTop;
if (selected) {
selected.points.forEach(n => {
n.x += e.movementX
n.y += e.movementY
})
ctx.clearRect(0, 0, can.width, can.height)
shapes.forEach(n => n.draw())
}
};
window.onmousedown = function() {
if (!selected) {
shapes.forEach(n => {
if (n.mouseIn(mouse)) {
selected = n
}
})
}
};
window.onmouseup = function() {
selected = null;
};
function PointInPoligon(points) {
return this.points
}
</script>
</body>
</html>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Решил изучать TypeScript; дошел до логовИмея опыт разработки в Java, выбор пал на библиотеку log4js
Подскажите, как к этому примеру прикрутить подписку на событие, например клик по кастомному контролу? Можно конечно в HTML написать, но это...
Всем приветПытаюсь понять как работаю css модули для вложеных компонентов
Нужно при помощи подпрограмм сформировать и вывести на экран массивы A[15] и B[14]И потом, при помощи функций найти их минумумы и максимумы