На страницах своего блога я уже рассказывал о том, как можно организовать добавление меток пользователями на карту, используя API Яндекс.Карт 2.х (1, 2 и 3).
Читатели блога задают вопрос, как можно сделать тоже, но через отдельную форму?
В этой заметке я расскажу как это сделать.

В начале мы подготовим нашу страницу с картой и формой добавления меток, для этого я буду использовать Twitter Bootstrap 3.
Вот код данной страницы:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<title>Добавление меток пользователями через отдельную форму - API Яндекс.Карт v2.x</title>
<!-- Bootstrap core CSS -->
<link href="css/bootstrap.css" rel="stylesheet">
<!-- Add custom CSS here -->
<link href="css/ymapstyle.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-lg-8">
<div id="map"></div>
<div id="res"></div>
</div>
<div class="col-lg-4">
<div class="panel">
<div class="panel-heading">
<h3 class="">
<i class="icon-envelope main-color"></i>
Добавить метку
</h3>
</div>
<div class="panel-body">
<!-- CONTACT FORM -->
<div id="add_marker">
<fieldset>
<div class="form-group">
<label for="name">Название</label><input class="form-control" type="text" name="name" id="marker_name" value="">
</div>
<div class="form-group">
<label for="hint_text">Подсказка</label><input class="form-control" type="text" name="hint_text" id="marker_hint" value=""><br>
</div>
<div class="form-group">
<label for="address">Адрес</label><input class="form-control" type="text" name="address" id="marker_address" value=""><br>
</div>
<div class="form-group">
<label for="balloon_text">Балун</label><textarea class="form-control" name="balloon_text" id="marker_balloontext" rows="5" cols="25"></textarea><br>
</div>
<div class="form-group">
<label>Значок метки:</label>
<div class="input-prepend"><span class="add-on"><img src="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/blue.png" style="height: 30px"></span>
<select name="image" id="image" class="form-control">
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/blue.png" value="twirl#blueIcon">twirl#blueIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/darkblue.png" value="twirl#darkblueIcon">twirl#darkblueIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/darkgreen.png" value="twirl#darkgreenIcon">twirl#darkgreenIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/darkorange.png" value="twirl#darkorangeIcon">twirl#darkorangeIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/green.png" value="twirl#greenIcon">twirl#greenIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/grey.png" value="twirl#greyIcon">twirl#greyIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/lightblue.png" value="twirl#lightblueIcon">twirl#lightblueIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/night.png" value="twirl#nightIcon">twirl#nightIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/orange.png" value="twirl#orangeIcon">twirl#orangeIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/pink.png" value="twirl#pinkIcon">twirl#pinkIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/red.png" value="twirl#redIcon">twirl#redIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/violet.png" value="twirl#violetIcon">twirl#violetIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/white.png" value="twirl#whiteIcon">twirl#whiteIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/yellow.png" value="twirl#yellowIcon">twirl#yellowIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/brown.png" value="twirl#brownIcon">twirl#brownIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/black.png" value="twirl#blackIcon">twirl#blackIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/airplane.png" value="twirl#airplaneIcon">twirl#airplaneIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/anchor.png" value="twirl#anchorIcon">twirl#anchorIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/badminton.png" value="twirl#badmintonIcon">twirl#badmintonIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/bank.png" value="twirl#bankIcon">twirl#bankIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/bar.png" value="twirl#barIcon">twirl#barIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/barberShop.png" value="twirl#barberShopIcon">twirl#barberShopIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/bicycle.png" value="twirl#bicycleIcon">twirl#bicycleIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/bowling.png" value="twirl#bowlingIcon">twirl#bowlingIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/buildings.png" value="twirl#buildingsIcon">twirl#buildingsIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/bus.png" value="twirl#busIcon">twirl#busIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/cafe.png" value="twirl#cafeIcon">twirl#cafeIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/camping.png" value="twirl#campingIcon">twirl#campingIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/car.png" value="twirl#carIcon">twirl#carIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/cellular.png" value="twirl#cellularIcon">twirl#cellularIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/cinema.png" value="twirl#cinemaIcon">twirl#cinemaIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/downhillSkiing.png" value="twirl#downhillSkiingIcon">twirl#downhillSkiingIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/dps.png" value="twirl#dpsIcon">twirl#dpsIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/dryCleaner.png" value="twirl#dryCleanerIcon">twirl#dryCleanerIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/electricTrain.png" value="twirl#electricTrainIcon">twirl#electricTrainIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/factory.png" value="twirl#factoryIcon">twirl#factoryIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/theater.png" value="twirl#theaterIcon">twirl#theaterIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/fishing.png" value="twirl#fishingIcon">twirl#fishingIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/gasStation.png" value="twirl#gasStationIcon">twirl#gasStationIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/gym.png" value="twirl#gymIcon">twirl#gymIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/hospital.png" value="twirl#hospitalIcon">twirl#hospitalIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/house.png" value="twirl#houseIcon">twirl#houseIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/keyMaster.png" value="twirl#keyMasterIcon">twirl#keyMasterIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/mailPost.png" value="twirl#mailPostIcon">twirl#mailPostIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/metroKiev.png" value="twirl#metroKievIcon">twirl#metroKievIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/metroMoscow.png" value="twirl#metroMoscowIcon">twirl#metroMoscowIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/metroStPetersburg.png" value="twirl#metroStPetersburgIcon">twirl#metroStPetersburgIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/metroYekaterinburg.png" value="twirl#metroYekaterinburgIcon">twirl#metroYekaterinburgIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/motobike.png" value="twirl#motobikeIcon">twirl#motobikeIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/mushroom.png" value="twirl#mushroomIcon">twirl#mushroomIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/phone.png" value="twirl#phoneIcon">twirl#phoneIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/photographer.png" value="twirl#photographerIcon">twirl#photographerIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/pingPong.png" value="twirl#pingPongIcon">twirl#pingPongIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/restauraunt.png" value="twirl#restaurauntIcon">twirl#restaurauntIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/ship.png" value="twirl#shipIcon">twirl#shipIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/shop.png" value="twirl#shopIcon">twirl#shopIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/skating.png" value="twirl#skatingIcon">twirl#skatingIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/stadium.png" value="twirl#stadiumIcon">twirl#stadiumIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/skiing.png" value="twirl#skiingIcon">twirl#skiingIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/smartphone.png" value="twirl#smartphoneIcon">twirl#smartphoneIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/workshop.png" value="twirl#workshopIcon">twirl#workshopIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/storehouse.png" value="twirl#storehouseIcon">twirl#storehouseIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/swimming.png" value="twirl#swimmingIcon">twirl#swimmingIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/tailorShop.png" value="twirl#tailorShopIcon">twirl#tailorShopIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/tennis.png" value="twirl#tennisIcon">twirl#tennisIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/tire.png" value="twirl#tireIcon">twirl#tireIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/truck.png" value="twirl#truckIcon">twirl#truckIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/train.png" value="twirl#trainIcon">twirl#trainIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/tramway.png" value="twirl#tramwayIcon">twirl#tramwayIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/trolleybus.png" value="twirl#trolleybusIcon">twirl#trolleybusIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/wifi.png" value="twirl#wifiIcon">twirl#wifiIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/wifiLogo.png" value="twirl#wifiLogoIcon">twirl#wifiLogoIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/turnLeft.png" value="twirl#turnLeftIcon">twirl#turnLeftIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/turnRight.png" value="twirl#turnRightIcon">twirl#turnRightIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/arrowDownLeft.png" value="twirl#arrowDownLeftIcon">twirl#arrowDownLeftIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/arrowDownRight.png" value="twirl#arrowDownRightIcon">twirl#arrowDownRightIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/arrowLeft.png" value="twirl#arrowLeftIcon">twirl#arrowLeftIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/arrowRight.png" value="twirl#arrowRightIcon">twirl#arrowRightIcon</option>
<option data-path="http://api.yandex.ru/maps/doc/jsapi/2.x/ref/images/styles/arrowUp.png" value="twirl#arrowUpIcon">twirl#arrowUpIcon</option>
</select></div>
</div><br>
</div>
<div class="form-group">
<label for="submit"> </label><input class="btn btn-lg btn-info" type="submit" name="submit" id="addmarker" value="Добавить">
</div>
<fieldset>
</div>
<!-- END CONTACT FORM -->
</div>
</div>
</div>
</div>
<footer>
<hr>
<div class="row">
<div class="col-lg-12">
<p>Copyright © webmap-blog.ru 2013</p>
</div>
</div>
</footer>
</div><!-- /.container -->
<!-- JavaScript -->
<script src="http://api-maps.yandex.ru/2.0/?load=package.full&lang=ru-RU" type="text/javascript"></script>
<script src="js/yandexmap.js"></script>
<script src="http://yandex.st/jquery/2.0.3/jquery.min.js"></script>
<script src="js/bootstrap.js"></script>
</body>
</html> |
К этому же файлу прилагаются еще несколько:
ymapstyle.css — файл с дополнительными стилями;
bootstrap.css — файл со стилями для Bootstrap 3;
yandexmap.js – здесь будет располагаться наш JavaScript-код для карты, получение значений из формы, передачи данных для записи в базу и вывод меток на карту.
В самом начале код файла yandexmap.js следующий:
var myMap;
ymaps.ready(init);
//Определение начальных параметров карты
function init () {
myMap = new ymaps.Map("map", {
center: [56.326944, 44.0075],
zoom: 12
}, {
balloonMaxWidth: 800
});
//Добавляем элементы управления
myMap.controls
.add('zoomControl')
.add('typeSelector')
.add('mapTools');
} |
Мы задаем начальные параметры для нашей карты и размещаем элементы управления.
Теперь нам необходимо получить данные из формы, провести геокодирование адреса и добавить метку на карту.
Для этого мы будем отслеживать событие клика по кнопке «Добавить».
Перед ним мы добавим еще немного кода:
— для смены изображения значка метки при выборе параметра select:
//Добавляем картинку при выборе опции select
$('#image').change(function(){
$('.add-on').find('img:first').attr('src', $('#image option:selected').attr('data-path'));
}); |
— задаем шаблон данных для балуна:
var MyBalloonContentLayoutClass = ymaps.templateLayoutFactory.createClass(
'<strong>$[properties.name]</strong>' +
' |
$[properties.description]
' ); |
Фрагмент кода для получения значений из формы:
$('#addmarker').click( function () {
var name = $('#marker_name').val();
var hintText = $('#marker_hint').val();
var address = $('#marker_address').val();
var balloonText = $('#marker_balloontext').val();
var stylePlacemark = $("#image option:selected").text(); |
Здесь код примерно тот же, что и в ранее упомянутых заметках, за исключением геокодирования.
Мы отправляем адрес геокодеру
var myGeocoder = ymaps.geocode(address);
myGeocoder.then(
function (res) {
var firstGeoObject = res.geoObjects.get(0);
coords = firstGeoObject.geometry.getCoordinates();
marker = new ymaps.Placemark(coords,
{
name: name,
description: balloonText,
hintContent: hintText
},{
balloonContentLayout: MyBalloonContentLayoutClass,
preset: stylePlacemark
});
$("#res").load("addmetki.php", {icontext: name, hinttext : hintText, balloontext : balloonText, styleplacemark : stylePlacemark, lat : firstGeoObject.geometry.getCoordinates()[0], lon : firstGeoObject.geometry.getCoordinates()[1]});
myMap.geoObjects.add(marker);
},
function (err) {
alert('Ошибка');
}
); |
И если нет ошибок, то добавляем метку на карту в точку с определёнными координатами.
После этого передаем параметры метки скрипту addmetki.php для сохранения в таблицу ymapapiv2_markers.
Файл vivodpointsmap.php посылает запрос к таблице ymapapiv2_markers и результат выборки отправлять в формате JSON.
За вывод меток на карту отвечает следующий код:
$.getJSON("vivodpointsmap.php",
function(json){
for (i = 0; i < json.markers.length; i++) {
var myPlacemark = new ymaps.Placemark([json.markers[i].lat,json.markers[i].lon], {
name: json.markers[i].icontext,
description: json.markers[i].balloontext,
hintContent: json.markers[i].hinttext
},{
balloonContentLayout: MyBalloonContentLayoutClass,
preset: json.markers[i].styleplacemark
});
// Добавляем метку на карту
myMap.geoObjects.add(myPlacemark);
}
}); |
Как видите всё очень похоже на предыдущий пример.
В заключении всем тем, кто интересуется тем, как организовать добавление меток пользователями на Яндекс.Карту, я подготовил бесплатную книгу, загрузить её можно здесь.
Далее я планирую продолжить данную тему и рассказать о том, как можно сделать редактирование уже добавленных меток.