Яндекс.Карта на Вашем сайте с возможностью добавления меток пользователями и вывод по категориям

Автор: | 13.05.2011

После публикации заметки «Яндекс.Карта на Вашем сайте с возможностью добавления меток пользователями. Новая версия.» меня начали спрашивать, как организовать вывод меток по категориям на карту.

В этой заметке я расскажу как это сделать.

Исходный код файлов мы возьмем из уже упоминавшейся заметки «Яндекс.Карта на Вашем сайте с возможностью добавления меток пользователями. Новая версия.»:

config.php — содержит код для соединения с базой данных;

vivodpoints.html — основной файл нашего решения, выводит карту с метками и в нем же реализована возможность добавления меток пользователями;

addpoint.php — в нем производится запись параметров о добавленной метки в базу данных;

vivodpointsmap.php — в этом файле производиться запрос к базе данных для выборки всех меток и формируется ответ в формате JSON.

В начале мы создаем в базе данных новую таблицу mappointscat.

Сделать это можно используя PhpMyAdmin выполнив следующий SQL-код:

CREATE  TABLE `mappointscat` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(255) NOT NULL,
  `descriptions` varchar(255) NOT NULL,
  `type` varchar(255) NOT NULL,
  `cx` varchar(10) NOT NULL,
  `cy` varchar(10) NOT NULL,
  `user` varchar(255) NOT NULL,
  `view` int(2) NOT NULL,
  PRIMARY KEY  (`id`)
)  ENGINE=MyISAM  DEFAULT CHARSET=utf8;

Здесь структура таблицы аналогична таблице mappoint, за исключением поля type, где мы будем хранить название категории.

Тепрерь, мы должны изменить файлы vivodpoints.html и addpoint.php.

В форму добавления параметров метки в файле vivodpoints.html добавить новое поле для выбора категории.

Для этого изменяем строку

var $element = YMaps.jQuery('<div>Название: <input type="text" id="name"/><br />Описание: <textarea id="descriptpoint" cols="20" rows="5"></textarea><br /><input type="button" value="Добавить" id="submit"/></div>');

На

var $element = YMaps.jQuery('<div>Название: <input type="text" id="name"/><br />Описание: <textarea id="descriptpoint" cols="20" rows="5"></textarea><br />Категория: <select id="type"><option value= "bar " SELECTED>Бар</option><option value="restaurant">Ресторан</option><option value="cafe">Кафе</option></select><br /><input type="button" value="Добавить" id="submit"/></div>');

И после строки

descriptpoint: $element.find(‘#descriptpoint’)[0].value,

добавляем

type: $element.find(‘#type option:selected’)[0].value,

А в файле addpoint.php принять переданный параметр, а затем записать все данные в таблицу базы данных.

Здесь добавляем строку $type = $_GET[‘type’]; перед $pcoord = $_GET[‘pcoord’];

И изменяе строку SQL-запроса к базе данных

$sql = "INSERT INTO mappoint VALUES(0, '$namepoint', '$descriptpoint', '$coordx', '$coordy', 'None', 1)";

На

$sql = "INSERT INTO mappointscat VALUES(0, '$namepoint', '$descriptpoint', '$type', '$coordx', '$coordy', 'None', 1)";

Новый код файла addpoint.php

<?php
 
header('Content-Type: text/html; charset=utf-8');
 
include ("config.php");
 
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
 
$namepoint = $_GET['namepoint'];
 
if (isset($_GET['namepoint']))       
{
$namepoint = $_GET['namepoint']; 
if ($namepoint == '') 
{
unset($namepoint);
}  
}
 
if (isset($_GET['descriptpoint']))       
{
$descriptpoint = $_GET['descriptpoint']; 
if ($descriptpoint == '') 
{
unset($descriptpoint);
}  
}
$type = $_GET['type'];
$pcoord = $_GET['pcoord'];
 
if (isset($namepoint) && isset($descriptpoint))
{
 
$namepoint = htmlspecialchars(trim($namepoint));
$descriptpoint = htmlspecialchars(trim($descriptpoint));
 
$exp_str1 = explode(",", $pcoord);
 
$coordx = $exp_str1[0];
$coordy = $exp_str1[1];
 
$sql = "INSERT INTO mappointscat VALUES(0, '$namepoint', '$descriptpoint', '$type', '$coordx', '$coordy', 'None', 1)";
$result = mysql_query($sql) or die("Ошибочный запрос: " . mysql_error());
if($result == true)
{
echo '{ success: true }';
}
else
{
echo '{ success: false, message: "Не удалось сохранить точку" }';
}
 
 
}
 
else 
 
{
echo '{ success: false, message: "Вы ввели не всю информацию, поэтому метка не может быть добавлена" }';
}
 
}
 
?>

Введем для примера несколько точек.

Теперь будем реализовывать вывод точек по категориям.

В начале рядом с картой добавим три ссылки для выбора категорий.

Поместим область с картой в таблицу.

В результате в разделе body будет следующий код:

<table>
    <tr>
        <td>
		<div id="YMapsID" style="width:800px;height:600px"></div>
		<div id="scriptmes"></div>
		</td>
        <td valign="top">
		<ul id="menu">
		<li><a href="#" id="bar" onclick="show_c('bar'); return false;">Бар</a></li>
		<li><a href="#" id="restaurant" onclick="show_c('restaurant'); return false;">Ресторан</a></li>
		<li><a href="#" id="cafe" onclick="show_c('cafe'); return false;">Кафе</a></li>
		</ul>
		</td>
    </tr>
<table>

Добавим еще стили.

<style type="text/css">       
            #menu {
                list-style: none;
 
                margin: 0;
                padding: 0;
            }
 
            #menu a {
                text-decoration: none;
 
                border-bottom: dashed 1px;
            }
 
            a.active {
                color: #000;
            }
    </style>

После этого мы добавляем функцию show_c для вывода меток для определенной категории.

function show_c(c){
YMaps.jQuery('#obj a').removeClass("active");
map.removeAllOverlays();
//Запрос данных и вывод маркеров на карту
YMaps.jQuery.getJSON("vivodpointsmap_echo2.php", {cat:c},
function(json){
for (i = 0; i < json.markers.length; i++) {
var placemark=new YMaps.Placemark(new YMaps.GeoPoint(json.markers[i].lat,json.markers[i].lng));
if(c == "bar"){placemark.setStyle("default#barIcon")};
if(c== "restaurant"){placemark.setStyle("default#restaurauntIcon")};
if(c== "cafe"){placemark.setStyle("default#cafeIcon")};
placemark.description= '<div style="color:#ff0303;font-weight:bold">'+json.markers[i].name+'</div>';
placemark.description = placemark.description+'<strong>Описание:</strong> '+json.markers[i].descriptions+'<br />Категория: '+json.markers[i].type;
map.addOverlay(placemark);
}
});
YMaps.jQuery('a#'+c).addClass("active");
return false;
}

И удаляем код обращения к файлу vivodpointsmap.php между строчками

map.enableScrollZoom(); и var myLayout = function (geoPoint) {

Рассмотрим функцию show_c подробнее.

В нее мы передаем параметр с названием категории c.

После этого, ссылку по которой произошел клик мы делаем не активной.

Удаляем все оверлеи с карты.

Делаем запрос к файлу vivodpointsmap.php передавая ему в качестве параметра наименование категории.

Затем полученный ответ в формате JSON мы обрабатываем и выводим метки для данной категории на карту.

А ссылку делаем активной.

И нам нужно немного изменить файл vivodpointsmap.php

Добавить строку $type = $_GET[‘cat’]; для получения переданного параметра наименования категории.

Из таблицы базы данных мы выбираем значения только для данной категории.

И формируем ответ в формате JSON.

Новый код файла vivodpointsmap.php

<?php
header('Content-Type: text/html; charset=utf-8');
 
include ("config.php");
 
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
 
//Сохранение русских букв(кирилицы) при использовании json_encode()
function json_encode_cyr($str) {
$arr_replace_utf = array('u0410', 'u0430','u0411','u0431','u0412','u0432',
'u0413','u0433','u0414','u0434','u0415','u0435','u0401','u0451','u0416',
'u0436','u0417','u0437','u0418','u0438','u0419','u0439','u041a','u043a',
'u041b','u043b','u041c','u043c','u041d','u043d','u041e','u043e','u041f',
'u043f','u0420','u0440','u0421','u0441','u0422','u0442','u0423','u0443',
'u0424','u0444','u0425','u0445','u0426','u0446','u0427','u0447','u0428',
'u0448','u0429','u0449','u042a','u044a','u042d','u044b','u042c','u044c',
'u042d','u044d','u042e','u044e','u042f','u044f');
$arr_replace_cyr = array('А', 'а', 'Б', 'б', 'В', 'в', 'Г', 'г', 'Д', 'д', 'Е', 'е',
'Ё', 'ё', 'Ж','ж','З','з','И','и','Й','й','К','к','Л','л','М','м','Н','н','О','о',
'П','п','Р','р','С','с','Т','т','У','у','Ф','ф','Х','х','Ц','ц','Ч','ч','Ш','ш',
'Щ','щ','Ъ','ъ','Ы','ы','Ь','ь','Э','э','Ю','ю','Я','я');
$str1 = json_encode($str);
$str2 = str_replace($arr_replace_utf,$arr_replace_cyr,$str1);
return $str2;
}
 
$type = $_GET['cat'];
 
$result = mysql_query("SELECT * FROM mappointscat WHERE type='$type'");
if(mysql_num_rows($result)>0)
{
while ($mar = mysql_fetch_array($result))
{
if($mar['type'] == 'bar') {$cattype = "Бар";}
if($mar['type'] == 'restaurant') {$cattype = "Ресторан";}
if($mar['type'] == 'cafe') {$cattype = "Кафе";}
 
$json =  array(name=>$mar['name'], descriptions=>$mar['descriptions'], type=>$cattype, lat=>$mar['cx'], lng=>$mar['cy']);
$markers[] = $json;
}
 
}
$points = array(markers=>$markers);
 
echo json_encode_cyr($points );
 
}			
 
?>

Если Вы формируете ответ через функцию echo

<?php
header('Content-Type: text/html; charset=utf-8');
 
include ("config.php");
 
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
 
$json = '{"markers" :['."n";
 
$type = $_GET['cat'];
 
$result = mysql_query("SELECT * FROM mappointscat WHERE type='$type'");
if(mysql_num_rows($result)>0)
{
while ($mar = mysql_fetch_array($result))
{
if($mar['type'] == 'bar') {$cattype = "Бар";}
if($mar['type'] == 'restaurant') {$cattype = "Ресторан";}
if($mar['type'] == 'cafe') {$cattype = "Кафе";}
 
$json =  $json.'{"name" : "'.$mar['name'].'", "descriptions" : "'.$mar['descriptions'].'", "type":"'.$cattype.'", "lat" : "'.$mar['cx'].'", "lng" : "'.$mar['cy'].'"},';
 
}
 
}
$json  = substr($json , 0,-1);
 
echo $json , ']}';
 
}			
 
?>

Посмотрим работу примера в действии.

Щелкая по карте, вы получаете форму для ввода параметров метки, с возможностью указания категории.

Уже сохраненные значения меток по категориям, можно вывести, нажав на соответствующую ссылку с права от карты.

Код измененного файла vivodpoints.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Яндекс.Карта на Вашем сайте с возможностью добавления меток пользователями. Новая версия</title>
 
<script src="http://api-maps.yandex.ru/1.1/index.xml?key=ACuF2EkBAAAAzahYCgIASLsFm9n8EPvNjaTc8nAWiETKgYcAAAAAAAAAAAC-q61vWtIK3Kzt2yQ9qFaGJGKzXw==" type="text/javascript"></script>
 
<script type="text/javascript">
 
var map;
 
window.onload = function () {
            map = new YMaps.Map(document.getElementById("YMapsID"));
            map.setCenter(new YMaps.GeoPoint(43.99150,56.31534), 12);
 
            map.addControl(new YMaps.TypeControl());
            map.addControl(new YMaps.ToolBar());
            map.addControl(new YMaps.Zoom());
            map.addControl(new YMaps.ScaleLine());
            map.enableScrollZoom();
 
 
var myLayout = function (geoPoint) {
   var $element = YMaps.jQuery('<div>Название: <input type="text" id="name"/><br />Описание: <textarea id="descriptpoint" cols="20" rows="5"></textarea><br />Категория: <select id="type"><option value="bar" SELECTED>Бар</option><option value="restaurant">Ресторан</option><option value="cafe">Кафе</option></select><br /><input type="button" value="Добавить" id="submit"/></div>');
   this.onAddToParent = function (parent) {
        $element.find('#submit').bind('click', function () {
              YMaps.jQuery.ajax({
                  url: 'addpoint2.php',
                  data: {
                       namepoint: $element.find('#name')[0].value,
					   descriptpoint: $element.find('#descriptpoint')[0].value,
					   type: $element.find('#type option:selected')[0].value, 
                       pcoord: geoPoint.toString()
                  },
 
            dataType: 'json',
                  // Это функция обработки ответа сервера
                  success: function (res) {
                       if (res.success) {
                             // если точка сохранилась, закрываем балун
                             map.closeBalloon();
                             // и ставим точку на карту
                             map.addOverlay(new YMaps.Placemark(geoPoint));
 
                       } else {                             
			YMaps.jQuery("#scriptmes").html('<p style="color:red">' + e.message + '</p>');
                       }
                  }
              });
 
        });
        $element.appendTo(parent);
   };
   this.onRemoveFromParent = function () {
        $element.remove();
   };
 
   this.update = function () {};
}
 
YMaps.Events.observe(map, map.Events.Click, function (map, e) {
     map.openBalloon(e.getCoordPoint(), new myLayout(e.getCoordPoint()));
});
 
} 
 
function show_c(c){
YMaps.jQuery('#obj a').removeClass("active");
map.removeAllOverlays();
//Запрос данных и вывод маркеров на карту
YMaps.jQuery.getJSON("vivodpointsmap_echo2.php", {cat:c},
function(json){
for (i = 0; i < json.markers.length; i++) {
var placemark=new YMaps.Placemark(new YMaps.GeoPoint(json.markers[i].lat,json.markers[i].lng));
if(c == "bar"){placemark.setStyle("default#barIcon")};
if(c== "restaurant"){placemark.setStyle("default#restaurauntIcon")};
if(c== "cafe"){placemark.setStyle("default#cafeIcon")};
placemark.description= '<div style="color:#ff0303;font-weight:bold">'+json.markers[i].name+'</div>';
placemark.description = placemark.description+'<strong>Описание:</strong> '+json.markers[i].descriptions+'<br />Категория: '+json.markers[i].type;
map.addOverlay(placemark);
}
});
YMaps.jQuery('a#'+c).addClass("active");
return false;
}
 
</script>   
 
</head>
 
<style type="text/css">       
            #menu {
                list-style: none;
 
                margin: 0;
                padding: 0;
            }
 
            #menu a {
                text-decoration: none;
 
                border-bottom: dashed 1px;
            }
 
            a.active {
                color: #000;
            }
    </style>
 
<body>
    <table>
    <tr>
        <td>
		<div id="YMapsID" style="width:800px;height:600px"></div>
		<div id="scriptmes"></div>
		</td>
        <td valign="top">
		<ul id="menu">
		<li><a href="#" id="bar" onclick="show_c('bar'); return false;">Бар</a></li>
		<li><a href="#" id="restaurant" onclick="show_c('restaurant'); return false;">Ресторан</a></li>
		<li><a href="#" id="cafe" onclick="show_c('cafe'); return false;">Кафе</a></li>
		</ul>
		</td>
    </tr>
<table>
 
 
 
</body>
</html>

Яндекс.Карта на Вашем сайте с возможностью добавления меток пользователями и вывод по категориям: 32 комментария

  1. mkone

    Очень круто а вы не могли бы написать про добавление в балун медиа контента например видео или фотографий я думаю такая возможность многим бы пригодилась
    или как вариант про добавление произвольного HTML код пользователем

  2. foX

    Спасибо за статью, пожалуй, это единственное в интернете решение моей проблемы. Вы не могли бы кинуть на мою почту архив с файлами, использующимися для создания карты-обращения к базе-добавления меток? История создания вашего шедевра разбросана по трем заметкам, копировать код по кускам и вносить изменения довольно сложно.

    1. admin Автор записи

      Эти config.php; vivodpoints.html; addpoint.php; vivodpointsmap.php ? Из заметки «Яндекс.Карта на Вашем сайте с возможностью добавления меток пользователями. Новая версия»

  3. Александр

    Добрый день, сделал всё как написано, но когда жму на карту выскакивает балун, я его заполняю жму добавить и ничего не происходит (балун не закрывается).
    P.S. Локальный сервер XAMPP

    1. admin Автор записи

      Запустите пример в браузере Firefox и посмотрите консоль ошибок. Еще можно установить расширение Firebug.

  4. Евгений

    >Добрый день, сделал всё как написано, но когда жму на карту выскакивает балун, я его заполняю жму добавить и ничего не происходит (балун не закрывается).

    Добрый день!
    Тоже самое получается и у меня( Автор помогите, если можно.

  5. Алексей

    Присоединяюсь к вопросу. Балун не закрывается, точка не добавляется.
    Но автору огромная благодарность за статью и подробное разжевывание!!!

    1. admin Автор записи

      Надо в файле карты vivodpoints.html прописать полный путь к файлам addpoint2.php и vivodpointsmap_echo2.php.
      Если они лежат в том же каталоге maps, тогда для файла addpoint2.php полный путь будет http://www.vyborg-portal.com/maps/addpoint2.php, а для vivodpointsmap_echo2.php — http://www.vyborg-portal.com/maps/vivodpointsmap_echo2.php

  6. Алексей

    Разобрался.
    В vivodpointsmap.html указаны строки:
    url: ‘addpoint2.php’
    YMaps.jQuery.getJSON(«vivodpointsmap_echo2.php», {cat:c},

    А в статье указаны имена: vivodpointsmap и addpoint.php
    Соответственно, меняем в коде названия файлов:
    url: ‘addpoint.php’
    YMaps.jQuery.getJSON(«vivodpointsmap.php», {cat:c},
    И все работает.

    Спасибо автору!!!

  7. Alexey

    У меня проблема. когда ввожу в балун многострочную информацию то потом не отображается метки всей категории.

    1. admin Автор записи

      Я уже исправил ошибку, надо до вывода данных в формате JSON добавить строку
      $descriptions = str_replace(«n», «», $mar[‘descriptions’]);,
      т.е. заменить все переводы строк на тег «».
      И дальше в коде в место $mar[‘descriptions’] использовать $descriptions.

  8. Dotrox

    Наверное, не $descriptions = str_replace(«n», «», $mar[‘descriptions’]);, а
    $descriptions = str_replace(«n», «», $mar[‘descriptions’]);

  9. Dotrox

    Хм, у вас в комментариях вырезаются HTML теги. Хотел в пустые кавычки вписать br, но его вырезало. Видимо у вас тоже:-)

  10. Виталий

    Уже пол-дня сижу, перепробовал всё, что тут написано, но хоть тресни — балун не закрывается, метка не ставится… Автор, есть какие-то соображения?

    1. admin Автор записи

      Аналогично, проверить путь к файлу addpoint.php

  11. ILYA

    А как сделать чтобы генерировалась ссылка для вставки карты на форум?

  12. Михаил

    А как добавить новые категории? В нескольких местах по добовлял но в балу все равно нету новой категории.

    1. admin Автор записи

      Для добавления новой категории необходимо:

      1. Добавить новую категорию в форму добавления метки, изменить сроку

      var $element = YMaps.jQuery('<div>Название: <input type="text" id="name"/><br />Описание: <textarea id="descriptpoint" cols="20" rows="5"></textarea><br />Категория: <select id="type"><option value="bar" SELECTED>Бар</option><option value="restaurant">Ресторан</option><option value="cafe">Кафе</option></select><br /><input type="button" value="Добавить" id="submit"/></div>');

      Например, добавить категорию кинотеатры, тогда строка будет иметь вид:

      var $element = YMaps.jQuery('<div>Название: <input type="text" id="name"/><br />Описание: <textarea id="descriptpoint" cols="20" rows="5"></textarea><br />Категория: <select id="type"><option value="bar" SELECTED>Бар</option><option value="restaurant">Ресторан</option><option value="cafe">Кафе</option><option value="cinima">Кинотеатр</option></select><br /><input type="button" value="Добавить" id="submit"/></div>');

      2. Изменить код файла vivodpointsmap.php, добавив после строки

      if($mar['type'] == 'cafe') {$cattype = "Кафе";}

      Строчку

      if($mar['type'] == 'cinima') {$cattype = "Кинотеатр";}

      3. Изменить функцию show_c(c) в файле vivodpoints-2.html, добавив после строки

      if(c== "cafe"){placemark.setStyle("default#cafeIcon")};

      строчку

      if(c== "cinima"){placemark.setStyle("default#cinemaIcon")}; - мы определяем стиль для обозначения меток новой категории Кинотеатр.

      4. Добавить новый пункт в меню карты.

      После строки

      <li><a href="#" id="cafe" onclick="show_c('cafe'); return false;" rel="nofollow">Кафе</a></li>

      Добавить

      <li><a href="#" id="cinima" onclick="show_c('cinima'); return false;" rel="nofollow">Кинотеатр</a></li>
  13. Михаил

    И как сделать чтобы по умолчанию все объекты из всех категорий показывались на карте?
    А то человек открывает пустую карту и не каждый додумается что можно нажать на категорию чтоб появились объекты.

    1. admin Автор записи

      Все просто, надо в основной функции после добавления элементов управления на карту, добавить три строки вызова функции вывода меток категории на карту:
      show_c(‘bar’);
      show_c(‘restaurant’);
      show_c(‘cafe’);

      Пример

  14. Михаил

    Ага, я не добавил как надо было в первом пункте, а в остальных добавлял)
    Еще раз спасибо, все отлично работает!

  15. Михаил

    Начал добавлять объекты на карту и понял что у яндекса очень ограничен выбор иконок. У гугла например намного больше ассортимент вот тут http://mapicons.nicolasmollet.com/category/markers/.
    Как не будь возможно поставить свои картинки иконок на карту?

  16. oskarton

    Здравствуйте.
    Спасибо большое за прекрасные руководства. Очень сильно помогли в вопросе возможности добавления меток пользователями сайта.
    Вот только с выведением меток по категориям у меня проблемы.
    Создаю в файле vivodpointsmap_echo2.php запрос к базе данных через echo, а не json_encode.
    На vivodpointsmap_echo2.php выводится вроде строка с данными, а на vivodpoints.html почему-то ничего не цепляется. Карта ошибок никаких не выдает,но и меток не выводит.
    В чем может быть причина?

  17. shelby

    А как заключить категории в селектор
    Делаю так:
    Бар

    и нет реакции (((
    Как быть ?

  18. shelby

    Куда именно это добавлять ?

    show_c(‘bar’);
    show_c(‘restaurant’);
    show_c(‘cafe’);

  19. Евгений

    Классно, автору огромное спасибо за блог! очень интересно!
    Только почему-то в данном примере добавляются и включаются на демо странице только кафе, два других пункта вроде бы добавляются, но при переключении пропадают (

  20. Олег

    Добрый день,уважаемый админ, большое спасибо за урок. очень помог, можно вас спросить как сделать
    1) при входе на сайт сразу отображались все объекты, с разными иконками,

    готов заплатить если это потребуется моя почта php84@bk.ru

  21. Алексей

    Автор, ты, конечно, молодец! Но не мог бы ты для слабоумных, как я, выложить исходники полноценной версии. Ну или хотя бы собрать все в одной статье, а то хрен разберешь где какая часть, запутано пипец просто…. 🙁

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *