Как сделать выделение произвольной области, как на domofond.ru? Удерживая нажато
левую кнопку мыши, двигаем курсор. Когда отпускаем, крайние точки замыкаются прямой, если фигура получилась незамкнутой.
Хочется реализовать так же, НЕ используя полигон и полилайн. Понятно, что в конечном итоге получится всё-равно полигон из очень маленьких отрезков.
Готовых решений не нашел. Все рекомендуют полигон, однако, повторюсь, он не подходит.
Допустим, я нарисую кривую на канвасе. Как разделить эту кривую на отрезки и ка
определить координаты точек на этой кривой? В какую сторону копать?
Ответы
Ответ 1
Внимание - в конце сообщения - обновление!
Если вы рисуете карандашом - то, по сути, это набор точек, или полилиния - только с маленьким шагом.
Как я понял проблема в аппроксимации этого набора точек. Есть такая библиотека
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;
}
Ответ 2
Скорее всего, вам подойдет Polyline (документация).
Очень просто будет получить координаты всех точек и обработать их как вам угодно.
Ответ 3
Изначально хотел предложить повесить канвас поверх карт, потом увидел, что polylin
позволяет получить желаемый результат, если конечно нет необходимости именно как карандашом проводить линии.
Вот пример: http://jsfiddle.net/at138o5y/
Скрипт:
var polyline;
ymaps.ready(init);
function init () {
var myMap = new ymaps.Map('map', {
center: [55.426541,37.768788],
zoom: 13
});
myMap.controls
.add('zoomControl')
.add('typeSelector')
.add('mapTools')
polyline = new ymaps.Polyline([], {}, {});
myMap.geoObjects.add(polyline);
polyline.editor.startEditing();
polyline.editor.startDrawing();
}
Комментариев нет:
Отправить комментарий