Страницы

Поиск по вопросам

вторник, 2 октября 2018 г.

Выделение произвольной области на яндекс картах(не полигон)

Как сделать выделение произвольной области, как на domofond.ru? Удерживая нажатой левую кнопку мыши, двигаем курсор. Когда отпускаем, крайние точки замыкаются прямой, если фигура получилась незамкнутой.
Хочется реализовать так же, НЕ используя полигон и полилайн. Понятно, что в конечном итоге получится всё-равно полигон из очень маленьких отрезков.
Готовых решений не нашел. Все рекомендуют полигон, однако, повторюсь, он не подходит.
Допустим, я нарисую кривую на канвасе. Как разделить эту кривую на отрезки и как определить координаты точек на этой кривой? В какую сторону копать?


Ответ

Внимание - в конце сообщения - обновление!
Если вы рисуете карандашом - то, по сути, это набор точек, или полилиния - только с маленьким шагом.
Как я понял проблема в аппроксимации этого набора точек. Есть такая библиотека - Simplify.js, она может упростить набор точек в ломанную линию.
Работает это по алгоритму Алгоритм Рамера — Дугласа — Пекера
Вот написал пример его работы - рисуйте на области канваса мышкой.
var canv = document.getElementById('canv'), ctx = canv.getContext('2d'), line = []; var startX = 0, startY = 0; function mouseDown(e) { ctx.clearRect(0, 0, canv.width, canv.height); startX = e.pageX - e.target.offsetLeft; startY = e.pageY - e.target.offsetTop; canv.addEventListener('mouseup', mouseUp); canv.addEventListener('mousemove', mouseMove); line = []; line.push({ x: startX, y: startY }); } function mouseMove(e) { var x = e.pageX - e.target.offsetLeft, y = e.pageY - e.target.offsetTop; ctx.beginPath(); ctx.moveTo(startX, startY); ctx.lineTo(x, y); ctx.stroke(); startX = x; startY = y; line.push({ x: x, y: y }); } function mouseUp() { canv.removeEventListener('mouseup', mouseUp); canv.removeEventListener('mousemove', mouseMove); aproximate(); } function aproximate() { ctx.clearRect(0, 0, canv.width, canv.height); var res = simplify(line, 5); console.log(res); ctx.save(); ctx.strokeStyle = 'red'; ctx.beginPath(); ctx.moveTo(res[0].x, res[0].y); res.forEach(function(el) { ctx.lineTo(el.x, el.y); }); ctx.stroke(); ctx.restore(); } canv.addEventListener('mousedown', mouseDown); canvas { border: 1px solid #aaa; }
Обновление: Набросок кода для рисования подобных линий на карте
Извиняюсь, что не очень красивый код - торопился.

var Map = (function() { ymaps.ready(init); var myMap; function init() { myMap = new ymaps.Map("map", { center: [57.5262, 38.3061], // Углич zoom: 11 }, { balloonMaxWidth: 200, searchControlProvider: 'yandex#search' }); addPolygon() } function convert(coords) { var projection = myMap.options.get('projection'); return coords.map(function(el) { var c = projection.fromGlobalPixels(myMap.converter.pageToGlobal([el.x, el.y]), myMap.getZoom()); return c; }); } function addPolygon(coord) { var myGeoObject = new ymaps.GeoObject({ geometry: { type: "Polygon", coordinates: [coord], }, }, { fillColor: '#00FF00', strokeColor: '#0000FF', opacity: 0.5, strokeWidth: 3 }); myMap.geoObjects.add(myGeoObject); } return { addPolygon: addPolygon, convert: convert }; })(); //---------------------- var canv = document.getElementById('canv'), ctx = canv.getContext('2d'), line = []; var map = document.getElementById('map'); canv.width = map.offsetWidth; canv.height = map.offsetWidth; var startX = 0, startY = 0; function mouseDown(e) { ctx.clearRect(0, 0, canv.width, canv.height); startX = e.pageX - e.target.offsetLeft; startY = e.pageY - e.target.offsetTop; canv.addEventListener('mouseup', mouseUp); canv.addEventListener('mousemove', mouseMove); line = []; line.push({ x: startX, y: startY }); } function mouseMove(e) { var x = e.pageX - e.target.offsetLeft, y = e.pageY - e.target.offsetTop; ctx.beginPath(); ctx.moveTo(startX, startY); ctx.lineTo(x, y); ctx.stroke(); startX = x; startY = y; line.push({ x: x, y: y }); } function mouseUp() { canv.removeEventListener('mouseup', mouseUp); canv.removeEventListener('mousemove', mouseMove); aproximate(); } function aproximate() { ctx.clearRect(0, 0, canv.width, canv.height); var res = simplify(line, 5); res = Map.convert(res); Map.addPolygon(res); } canv.addEventListener('mousedown', mouseDown); html, body, #map { width: 100%; height: 100%; padding: 0; margin: 0; overflow: hidden; } canvas { border: 1px solid #aaa; position: absolute; z-index: 99999; top: 0; left: 0; }


Комментариев нет:

Отправить комментарий