На страницах своего блога я уже неоднократно писал о том, как можно организовать добавление меток пользователями на Яндекс.Карту (смотрите заметки — 1, 2, 3 и 4).
Время идет и я получаю новые знания, которыми и хочу поделиться со своими читателями.
В этой заметке я хочу представить новую версию решения данной задачи, реализованную с использованием технологии AJAX и формата данных JSON.
В этой версии мы будем использовать четыре файла.
- config.php — содержит код для соединения с базой данных;
- vivodpoints.html — основной файл нашего решения, выводит карту с метками и в нем же реализована возможность добавления меток пользователями;
- addpoint.php — в нем производится запись параметров о добавленной метки в базу данных;
- vivodpointsmap.php — в этом файле производиться запрос к базе данных для выборки всех меток и формируется ответ в формате JSON.
И так начнем.
В начале нам необходимо в базе данных MySQL создать таблицу для хранения данных пользователей.
Сделать это можно используя PhpMyAdmin выполнив следующий SQL-код:
CREATE TABLE `mappoint` ( `id` int(11) NOT NULL auto_increment, `name` varchar(255) NOT NULL, `descriptions` 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; |
Код файла для соединения с базой данных config.php:
<?php $sdb_name = "localhost"; $user_name = "userymap"; $user_password = "123"; $db_name = "ymap_bd"; // соединение с сервером базы данных if(!$link = mysql_connect($sdb_name, $user_name, $user_password)) { echo "<br>Не могу соединиться с сервером базы данных<br>"; exit(); } // выбираем базу данных if(!mysql_select_db($db_name, $link)) { echo "<br>Не могу выбрать базу данных<br>"; exit(); } mysql_query('SET NAMES utf8'); ?> |
Здесь ymap_bd — имя нашей базы данных, userymap и 123 — логин и пароль для доступа к базе соответственно.
Давайте сначала посмотрим работу примера в действии, а потом я поясню код каждого из файлов.
При загрузке страницы с картой в браузере, мы наблюдаем Яндек.Карту с добавленными метками.
Если щелкнуть левой кнопкой мыши по карте, то откроется балун с формой для ввода названия и описания метки.
После ввода значений нажимаем на кнопку Добавить, метка появляется на карте.
Рассмотрим код основного файла 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=ACuF2bkBAAAAzahYCgIASggsFm9n8EPvNjaTc8nAWiETKgYcAAAAAAAAAAAC-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(); //Запрос данных и вывод маркеров на карту YMaps.jQuery.getJSON("vivodpointsmap.php", 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), {style: "default#redSmallPoint"}); placemark.description= '<div style="color:#ff0303;font-weight:bold">'+json.markers[i].name+'</div>'; placemark.description = placemark.description+'<strong>Описание:</strong> '+json.markers[i].descriptions; map.addOverlay(placemark); } }); var myLayout = function (geoPoint) { 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>'); this.onAddToParent = function (parent) { $element.find('#submit').bind('click', function () { YMaps.jQuery.ajax({ url: 'addpoint.php', data: { namepoint: $element.find('#name')[0].value, descriptpoint: $element.find('#descriptpoint')[0].value, pcoord: geoPoint.toString() }, dataType: 'json', // Это функция обработки ответа сервера success: function (res) { if (res.success) { // если точка сохранилась, закрываем балун map.closeBalloon(); // и ставим точку на карту map.addOverlay(new YMaps.Placemark(geoPoint)); } else { // иначе выдаем сообщение об ошибке // YMaps.jQuery('<p style="color:red">' + e.message + '</p>').appendTo("#scriptmes"); 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())); }); } </script> </head> <body> <div id="YMapsID" style="width:800px;height:600px"></div> <div id="scriptmes"></div> </body> </html> |
В начале мы задаем параметры нашей карты и добавляем элементы управления.
Затем мы делаем запрос к файлу vivodpointsmap.php для вывода данных из таблицы и формирования ответа в формате JSON, полученные данные о метках, мы отображаем на карте.
И самая интересная часть.
При клике по карте на нее добавляется элемент с формой для ввода параметров метки.
А после нажатия кнопки Добавить формы, введенные данные передаются в файл addpoint.php, в котором заносятся в базу данных.
На карте же, если все прошло успешно, в месте клика появляется новая метка.
В случае ошибки выводится сообщение.
Теперь рассмотрим код файла addpoint.php
<?php header('Content-Type: text/html; charset=utf-8'); require ("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); } } $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 mappoint VALUES(0, '$namepoint', '$descriptpoint', '$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: "Вы ввели не всю информацию, поэтому метка не может быть добавлена" }'; } } ?> |
В этом файле введенные в форму параметры принимаются методом GET и заносятся в базу данных.
В случае успеха в ответ отправляется сообщение в формате JSON — { success: true }.
А в случае ошибки — { success: false, message: «Не удалось сохранить точку» }
И последний файл vivodpointsmap.php
<?php header('Content-Type: text/html; charset=utf-8'); require ("config.php"); if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { $result = mysql_query("SELECT * FROM mappoint"); if(mysql_num_rows($result)>0) { while ($mar = mysql_fetch_array($result)) { $json = array(name=>$mar['name'], descriptions=>$mar['descriptions'], lat=>$mar['cx'], lng=>$mar['cy']); $markers[] = $json; } } $points = array(markers=>$markers); echo json_encode($points); } ?> |
Здесь мы выбираем из таблицы mappoint все данные о метках и формируем из них массив.
Затем используя команду json_encode, мы формируем ответ в формате JSON.
Тут есть два момента на которые нужно обратить внимание.
- Функция json_encode работает с версией PHP 5 > >= 5.2.0, если эта функция у Вас не работает можно
использовать библиотеку http://pear.php.net/package/Services_JSON
Тогда вместо строки echo json_encode($points ); нужно писать
require_once ‘Classes/json.php’;
$json = new Services_JSON;
$json_data = $json->encode($data);
- При работе с кириллицей русские буквы преобразуются в коды, чтобы этого не происходило в окончательном варианте кода я использовал специальную функцию.
<?php header('Content-Type: text/html; charset=utf-8'); require ("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; } $result = mysql_query("SELECT * FROM mappoint"); if(mysql_num_rows($result)>0) { while ($mar = mysql_fetch_array($result)) { $json = array(name=>$mar['name'], descriptions=>$mar['descriptions'], lat=>$mar['cx'], lng=>$mar['cy']); $markers[] = $json; } } $points = array(markers=>$markers); echo json_encode_cyr($points ); } ?> |
Если по каким-либо причинам, Вам не удалось получить ответ в формате JSON, то в этом случае можно воспользоватся оператором echo.
Тогда код файла addpoint.php будет таким:
<?php header('Content-Type: text/html; charset=utf-8'); require ("config.php"); if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { $json = '{"markers" :['."n"; $result = mysql_query("SELECT * FROM mappoint"); if(mysql_num_rows($result)>0) { while ($mar = mysql_fetch_array($result)) { $json = $json.'{"name" : "'.$mar['name'].'", "descriptions" : "'.$mar['descriptions'].'", "lat" : "'.$mar['cx'].'", "lng" : "'.$mar['cy'].'"},'; } } $json = substr($json , 0,-1); echo $json , ']}'; } ?> |
При написании данной заметки использовались следующие источники:
Ты просто молодец. А на каком ты сайте все это используешь?
-При работе с кириллицей русские буквы преобразуются в коды
В первом варианте все отлично работает, все по-русски. А вот при добавлении функции json_encode_cyr, наоборот…
такая бага, при добавлении метки, она добавляется и отображается синим, при нажатии на нее текст не выводится, при перезагрузке страницы метка становится красной и текст доступен
Это не баг, так специально задумано. После добавления сразу видно какая метка добавлена
Ждал этой статьи. Пишу на PHP много лет, а в javascript, увы, полный ноль.
Насколько сложно пример из этого урока скрестить с группами объектов (для вывода меток в зависимости от категорий, типа: Кафе, Театр)?
Не так сложно. Нужно сделать выбор категорий, например с помощью чекбоксов, а файл выбора меток из базы изменить так, чтобы выбирались данные о метках только выбранных категорий.
Отлично! Спасибо большое все получилось. http://vostokblog.com/informacija/map.html
Автор скажите пожалуйста как сделать так чтобы метки можно было удалить, допустим нажав на метку при просмотре была кнопочка удалить?
Присоединяюсь к Ивану по поводу групп, хотя бы чтобы метки имели нумерацию, возможно сделать?
Спасибо автор! Это как раз то, что мне нужно =)
Есть вопрос: возможно ли сделать так, чтобы пользователь мог менять инфу в описании уже имеющейся точки?
Ещё раз спасибо!
И ещё вопрос, можно ли заменить значок метки на свой?
Да, в строке var placemark=new YMaps.Placemark(new YMaps.GeoPoint(json.markers[i].lat,json.markers[i].lng), {style: «default#redSmallPoint»}); прописывается стиль для метки. Можно определить свой и заменить default#redSmallPoint на имя своего стиля.
Понятно, спасибо. =)
1. После публикации новой метки нет ее названия и описания и если пользователь ставит их штук 5-6 легко может запутаться .. поэтому на мой взгляд код нужно дополнить ( в vivodpoints.html):
….
var nam,desc; // ! объявляем переменные
var myLayout = function (geoPoint) {
var $element = YMaps.jQuery(‘Название: Описание: Фотография’);
this.onAddToParent = function (parent) {
$element.find(‘#submit’).bind(‘click’, function () {
YMaps.jQuery.ajax({
url: ‘addpoint.php’,
data: {
namepoint: nam = $element.find(‘#name’)[0].value,
descriptpoint: desc = $element.find(‘#descriptpoint’)[0].value,
pcoord: geoPoint.toString()
},
dataType: ‘json’,
// Это функция обработки ответа сервера
success: function (res) {
if (res.success) {
// если точка сохранилась, закрываем балун
map.closeBalloon();
// и ставим точку на карту
var Placemark = new YMaps.Placemark(geoPoint, {style: «default#whiteSmallPoint»});
// ! Добавляем имя новой метки и описание
Placemark.name = nam;
Placemark.description = desc;
map.addOverlay(Placemark);
} else {
// иначе выдаем сообщение об ошибке
// YMaps.jQuery(» + e.message + »).appendTo(«#scriptmes»);
YMaps.jQuery(«#scriptmes»).html(» + e.message + »);
}
}
});
});
$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()));
});
И еще.. Непонятно почему, но начиная со втрой метки информация в базу записывается дважды!! И метки на карту наносятся по две штуки на точку (но как то опять же через раз) В общем баг.
Вопрос с двойными метками, ответ на предыдущий пост, решен. Все просто, как и все гениальное — нужно в файлах addpoint.php и vivodpointsmap.php вместо » include («config.php»); » использовать » require («config.php»); » Автор, исправьте код пожалуйста, и спасибо за исходник..
Отлично! Отличный сайт! Отличные мануалы!
Жму руку автору!
Относительно статьи… Всё понял и всё получилось!
А на php 5.3 будет работать?
Наверно, надо проверить
Здравствуйте,
можете доработать компонент или плагин для Joomla 1.5, что бы так же возможно было метки добавлять пользователями сайта
Доработать можно, но только через некоторое время
Компонент(но не плагин) был бы очень полезным, надеюсь админ поможет нам
Уважаемые администраторы подскажите можно ли карту с категориями выложить на сайт ucoz.ru , и как это можно сделать с помощью скрипта ?
Попробуйте это ссылка
Неужели нет программиста который добавит параметр удаление , редактирование
меток ?
Автор скажите пожалуйста как сделать так чтобы метки можно было удалить, допустим нажав на метку при просмотре была кнопочка удалить или редактировать ?
Тестировал на локалке (денвер) все ок.
Почему-то не работает скрипт на хостинге
Системные требования php5.2 (при включенном json) и mysql5 соответствуют.
При щелчке в произвольном месте карты появляется форма заполняем жмем добавить и метка на карту не добавляется. Кнопка «Добавить» какая-то дохлая.
Пдскажите в чем может быть причина?
Проверьте путь к php файлам для добавления и формирования файла JSON, напишите полный путь начиная с http://
Прописывал и полный путь то же самое.
Хостер говорит, что на денвере всё включено, потому там и работает
а на хостинге кое какие модули закрываем, надо узнать что именно включить.
Прошу включить все, говорит что их о-очень много узнайте у разработчика что именно необходимо для работы скрипта.
Просят уточнить системные требования к скрипту.
Оказалось файл .htaccess был причиной. Теперь метка появляется, но после перезагрузки страницы пропадает почему-то.
Как .htaccess написать правильно чтобы все работало?
У меня такая же проблема, все прекрасно работало, метки сохранялись и выводились, но потом поставил доступ в htaccess только с моего айпи, и все метки ушли
Обнулил htaccess, прописывал даже allow from all. Но ничего не помогает, метки не выводятся.
Как исправить проблему не знаю, кажется что json и htaccess не дружат друг с другом
Админ помоги
извините, все нормально, ошибка была в конфиг пхп
Подскажите каким образом в балун добавления метки добавить возможность добавления файла в метку? (в базе записывать только путь закачки файла на хост)
HELP!
У меня проблема с двойной записью в базу, не могу найти решение проблемы, подскажите пожалуйста
Смотрите решение здесь
Добрый день! Всё сделал, так как описано, но выдает такую ошибку: «неправильный ключ». Что значит неправильный ключ?
Это значит, что ключ к API Яндекс.Карт не подходит для Вашего домена.
Подробнее о ключах
Для localhost можно использовать любой ключ
Про неправильный ключ я задал вопрос, когда пытался вставить карту на блог WordPress. Может на WordPress не будет работать? И второй вопрос: сделал то-же самое на локалке, карта появилась, но когда нажимаю левой кнопкой мыши, чтобы добавить метку, балун появляется, но при нажатии на кнопку «Добавить», ничего не происходит… SOS!!!
Проверьте правильно указан путь к файлу addpoint.php. Он отвечает за запись данных.
Путь указан верно. Вот ссылка на страницу с картой сайта: http://www.ivanovo.ws/maps.php/
Кто может помочь в вопросом, о котором говорилось выше? Есть знающие люди?
Спасибо за урок. Но выяснилось, что не отображаются добавленне метки в IE9. т.е в базу все попадает,а на экран не выводится. В Хроме все Ок.
в Уточнение к предыдущему сообщению. Метки в IE9 появляются только после закрытие IE и очистки временных файлов.