API Яндекс.Карт – рисуем полилинию и сохраняем ее в базе данных MySQL

В этой заметке я продолжаю тему начатую в записи «API Яндекс.Карт – рисуем полилинию».

Здесь мы сохраним нарисованную ломаную линию в базе данных MySQL, а затем выведем ее на карту.

Для сохранения полилинии нам необходимо создать таблицу userslineymap в базе данных.

Сделать это можно с помощью следующего SQL-кода:

CREATE TABLE `userslineymap` (
`id_line` int(20) NOT NULL auto_increment,
`colour` varchar(10) NOT NULL,
`width` int(10) NOT NULL,
`users` varchar(255) NOT NULL,
`coordinats` text NOT NULL,
PRIMARY KEY  (`id_line`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

id_line – здесь хранится порядковый номер записи в таблице, происходит его автоматическое увеличение на единицу при добавлении новой записи;

colour – служит для хранения цвета полилинии, например, красный – ff0000;

width – этот параметр отвечает за толщину полилинии;

users – параметр для хранения имени пользователя , добавившего полилинию – в нашем примере не используется, но если вы захотите учитывать пользователей – это поле вам понадобиться;

coordinats – хранятся координаты вершин полилинии в виде текстовой строки, пары значений разделяются между собой точкой с запятой.

Еще одно замечание, в базе данных MySQL реализована поддержка пространственных расширений, чтобы позволяет хранить и анализировать  географические свойства, но для нашего примера мы будем использовать обычное текстовое поле для хранения координат.

Теперь мы напишем два php-скрипта для соединения с базой данных config.php и для записи данных в таблицу userslineymap — upload.php

Код файла config.php:

<?php
 
$sdb_name = "localhost";
$user_name = "root";
$user_password = "";
$db_name = "gmapsbd";
 
// соединение с сервером базы данных
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');
 
?>

Код файла upload.php:

<?php
 
include("config.php");
 
$points = trim($_POST['coords']);
 
$result = mysql_query ("INSERT INTO userslineymap VALUES (0, '#FF0000', 2, ' ', '$points')");
 
?>

Тут тоже все очень просто.

Мы принимаем строку со значениями координат вершин полилинии вида 43.984359,56.319304;43.995346,56.313389;44.010109,56.324168;44.036544,56.311099;44.049934,56.318827.040664,56.3111942, переданную методом POST.

Убираем лишние переводы строк и пробелы, а затем, с помощью оператора INSERT записываем ее в нашу таблицу, а также толщину линии и ее цвет.

Для того чтобы, передать значения координат в скрипт upload.php необходимо в код, который мы получили в предидущей заметке «API Яндекс.Карт – рисуем полилинию» — http://webmap-blog.ru/examples/ymap_pr_45.html  после  строки

YMaps.jQuery("#coords").attr("value", polyline.getPoints().join(‘n’));

Еще одну строку кода:

YMaps.jQuery.post("upload.php", {coords : polyline.getPoints().join(‘;’)});

Здесь используя встроеную JavaScript-библиотеку jQuery асинхронно методом POST, передаем значения   координат   вершин ломаной линии в наш php-скрипт upload.php, разделяя пары значений широты и долготы точкой с запятой.

Приведу полный код примера:

<!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> 
    <title>API Яндекс.Карт - рисуем полилинию и сохраняем в БД MySQL</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    <script src="http://api-maps.yandex.ru/1.1/index.xml?key=ACuF2EkBAAAAzahYCgIASLsFm9n8EPvNjaTc8nAWiETKgYcAAAAAAAAAAAC-q61vWtIK3Kzt2yQ9qFaGJGKzXw==" type="text/javascript"></script> 
 
	<script type="text/javascript"> 
 
	var polyline
 
        // Создание обработчика для события window.onLoad
        YMaps.jQuery(function () {
            // Создание экземпляра карты и его привязка к созданному контейнеру
            var map = new YMaps.Map(YMaps.jQuery("#YMapsID")[0]);
 
            // Установка для карты ее центра и масштаба
            map.setCenter(new YMaps.GeoPoint(43.998779,56.316537), 13);
 
			map.addControl(new YMaps.Zoom());
	        map.addControl(new YMaps.TypeControl());
	        map.addControl(new YMaps.ToolBar());
 
            // Создание ломанной
            var polyline = new YMaps.Polyline();
 
            // Установка параметров режима редактирования
            polyline.setEditingOptions({
			drawing: true,
                 menuManager: function (index, menuItems) {
                    menuItems.push({
                        id: "StopEditing",
                        title: '<span style="white-space:nowrap;">Завершить редактирование<span>',
                        onClick: function (polyline, pointIndex) {
                       polyline.stopEditing();	                      		
                       YMaps.jQuery("#coords").attr("value", polyline.getPoints().join('n'));
                       YMaps.jQuery.post("upload.php", {coords : polyline.getPoints().join(';')});					   
                        }
                    });
                    return menuItems;
                }
            });        
 
            // Добавление ломаной на карту
            map.addOverlay(polyline);		
 
 
            // Включение режима редактирования
            polyline.startEditing();
 
        })
    </script> 
</head> 
 
<body> 
<table> 
 <tr> 
  <td>
     <div id="YMapsID" style="width:800px;height:600px"></div>
	</td>
	<td valign="top">
	 <textarea rows="15" cols="35" id="coords" name="coord"></textarea>
	</td>
	</tr>
	</table>
	<p><a href="/?p=" title="API Яндекс.Карт – рисуем полилинию и сохраняем ее в базе данных MySQL" target="_blank">Вернуться к тексту заметки</a></p>
 
</body> 
</html>

Посмотреть пример в действии

Теперь нам нужно вывести, сохраненные в базе данных полилинии, на карту.

Удобнее всего для этого использовать файл в формате YMapsML и подгружать его на карту.

За создание YMapsML-файла будет отвечать скрипт – viv-xml.php

Для простоты я не буду в коде учитывать толщину линии и цвет, т.е. для отображения всех полилиний я буду использовать один стиль.

Приведу код файла viv-xml.php:

<?php
 
header("Content-type: text/xml");
 
include("config.php");
 
echo '<?xml version="1.0" encoding="utf-8"?>
<ymaps:ymaps xmlns:ymaps="http://maps.yandex.ru/ymaps/1.x" xmlns:repr="http://maps.yandex.ru/representation/1.x" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maps.yandex.ru/schemas/ymaps/1.x/ymaps.xsd"> 
    <repr:Representation>
		<repr:Style gml:id="customStyle"> 
			<repr:lineStyle> 
				<repr:strokeColor>FF9911</repr:strokeColor> 
				<repr:strokeWidth>4</repr:strokeWidth> 
			</repr:lineStyle> 
		</repr:Style> 
		<repr:Style gml:id="customStyle1"> 
			<repr:parentStyle>#customStyle</repr:parentStyle> 
			<repr:lineStyle> 
				<repr:strokeColor>FF00FF</repr:strokeColor> 
			</repr:lineStyle> 
		</repr:Style>		
	</repr:Representation> 
	<ymaps:GeoObjectCollection> 
		<gml:name>Полилинии из базы данных</gml:name>
		<gml:featureMembers>';
 
 
$result = mysql_query("SELECT id_line, coordinats FROM userslineymap");
if(mysql_num_rows($result)>0)
            {
			while ($mar = mysql_fetch_array($result))
            {
			echo '<ymaps:GeoObject>'; 
			echo '<gml:name>Маршрут-', $mar['id_line'], '</gml:name>';
			echo '	<gml:description>Маршрут в виде ломаной</gml:description>';
			echo '	<gml:LineString> ';
 
			$str_exp1 = explode(";", $mar['coordinats']);
			for($i=0; $i<count($str_exp1); $i++)
			{
			$str_exp2 = explode(",", $str_exp1[$i]);
			echo '<gml:pos>', $str_exp2[0], ' ', $str_exp2[1], '</gml:pos>';
			}
 
			echo '</gml:LineString><ymaps:style>#customStyle1</ymaps:style></ymaps:GeoObject> ';
 
			}
 
			}			
 
echo '</gml:featureMembers> 
	</ymaps:GeoObjectCollection> 
</ymaps:ymaps>';
 
?>

Здесь с использованием оператора echo, формируется код YMapsML-файла.

Для вывода, сформированного файла на карту, используется файл viv-ymapsml.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> 
    <title>Выводим полилинии из базы данных MySQL</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    <script src="http://api-maps.yandex.ru/1.1/index.xml?key=ACuF2EkBAAAAzahYCgIASLsFm9n8EPvNjaTc8nAWiETKgYcAAAAAAAAAAAC-q61vWtIK3Kzt2yQ9qFaGJGKzXw==" type="text/javascript"></script> 
    <script language="JavaScript" type="text/javascript"> 
        // Создание обработчика для события window.onLoad
        YMaps.jQuery(function () {
            // Создание экземпляра карты и его привязка к созданному контейнеру
            var map = new YMaps.Map(YMaps.jQuery("#YMapsID")[0]);
 
            // Установка для карты ее центра и масштаба
            map.setCenter(new YMaps.GeoPoint(43.998779,56.316537), 13);
 
			map.addControl(new YMaps.Zoom());
	        map.addControl(new YMaps.TypeControl());
	        map.addControl(new YMaps.ToolBar());
 
            // Создание и добавление YMapsML-документа на карту
            var ml = new YMaps.YMapsML("http://webmap-blog.ru/examples/drawline/viv-xml.php");
            map.addOverlay(ml);
 
            // Обработчик неудачной загрузки YMapsML
            YMaps.Events.observe(ml, ml.Events.Fault, function (ml, error) {
                alert('Ошибка: ' + error);
            });
        });
	</script> 
</head> 
 
<body> 
    <div id="YMapsID" style="width:800px; height:600px;"></div> 
</body> 
</html>

Посмотреть пример в действии

Здесь все полилинии выводятся одновременно.

Возможно, выводить полилинии на карту по отдельности, выбирая нужную из меню.

Для этого нам необходимо немного изменить код файла ymapsml.html

Для его изменения я использовал пример «Создание меню для отображения коллекций объектов »

В файле ymapsml.html нужно удалить строку map.addOverlay(ml); — добавление оверлея на карту.

Добавить следующие фрагменты кода:

— Обработчик успешной загрузки YMapsML-файла

YMaps.Events.observe(ml, ml.Events.Load, function (ml) {
// Создание списка групп
ml.get(0).forEach(function (item) {
addMenuItem(item, map, YMaps.jQuery("#menu"));
});
});

С разу после создания YMapsML-документа

var ml = new YMaps.YMapsML("http://webmap-blog.ru/xml/pline-pr1.xml");

Переменную map сделать глобальной, объявив ее до функции с оздание обработчика для события window.onLoad.

И добавить функцию addMenuItem для добавления пунктов меню

function addMenuItem (group, map, menuContainer) {

// Показать/скрыть группу на карте
YMaps.jQuery("<a class="title" href="#">" + group.name + "</a>")
.bind("click", function () {
var link = YMaps.jQuery(this);

// Если пункт меню "неактивный", то добавляем группу на карту,
// иначе — удаляем с карты
if (link.hasClass("active")) {
map.removeOverlay(group);
} else {
map.addOverlay(group);
}

// Меняем "активность" пункта меню
link.toggleClass("active");

return false;
})

// Добавление нового пункта меню в список
.appendTo(
YMaps.jQuery("<li></li>").appendTo(menuContainer)
)
};

Еще мы добавляем строку для объекта меню в секцию body и задаем стиль для пунктов меню.

В результате у нас должен получиться следующий код:

<!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> 
    <title>Выводим полилинии из базы данных MySQL и создаем меню</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    <script src="http://api-maps.yandex.ru/1.1/index.xml?key=ACuF2EkBAAAAzahYCgIASLsFm9n8EPvNjaTc8nAWiETKgYcAAAAAAAAAAAC-q61vWtIK3Kzt2yQ9qFaGJGKzXw==" type="text/javascript"></script> 
    <script language="JavaScript" type="text/javascript">
 
	var map;
 
        // Создание обработчика для события window.onLoad
        YMaps.jQuery(function () {
            // Создание экземпляра карты и его привязка к созданному контейнеру
            map = new YMaps.Map(YMaps.jQuery("#YMapsID")[0]);
 
            // Установка для карты ее центра и масштаба
            map.setCenter(new YMaps.GeoPoint(43.998779,56.316537), 13);
 
			map.addControl(new YMaps.Zoom());
	        map.addControl(new YMaps.TypeControl());
	        map.addControl(new YMaps.ToolBar());
 
            // Создание и добавление YMapsML-документа на карту
            var ml = new YMaps.YMapsML("http://webmap-blog.ru/examples/drawline/viv-xml.php");
 
           // Обработчик успешной загрузки
            YMaps.Events.observe(ml, ml.Events.Load, function (ml) {
                // Создание списка групп
                ml.get(0).forEach(function (item) {
                    addMenuItem(item, map, YMaps.jQuery("#menu"));
                });
            });
 
            // Обработчик неудачной загрузки
            YMaps.Events.observe(ml, ml.Events.Fault, function (ml, error) {
                alert("При загрузке данных произошла ошибка: " + error);
            });
        })
 
        // Добавление одного пункта в список
        function addMenuItem (group, map, menuContainer) {
 
            // Показать/скрыть группу на карте
            YMaps.jQuery("<a class="title" href="#">" + group.name + "</a>")
                .bind("click", function () {
                    var link = YMaps.jQuery(this);
 
                    // Если пункт меню "неактивный", то добавляем группу на карту,
                    // иначе - удаляем с карты
                    if (link.hasClass("active")) {
                        map.removeOverlay(group);
                    } else {
                        map.addOverlay(group);
                    }
 
                    // Меняем "активность" пункта меню
                    link.toggleClass("active");
 
                    return false;
                })
 
                // Добавление нового пункта меню в список
                .appendTo(
                    YMaps.jQuery("<li></li>").appendTo(menuContainer)
                )
        };
    </script> 
 
    <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> 
 
</head> 
 
<body> 
    <table> 
    <tr> 
        <td><div id="YMapsID" style="width:800px;height:600px"></div></td> 
        <td valign="top"><ul id="menu"></ul></td> 
    </tr> 
    <table> 
	<p><a href="/?p=" title="API Яндекс.Карт – рисуем полилинию и сохраняем ее в базе данных MySQL" target="_blank">Вернуться к тексту заметки</a></p>
</body> 
 
</html>

Выбирая тот или иной пункт меню, отображаются разные полилинии.

Посмотреть пример в действии

На этом я еще не заканчиваю рассмотрение темы работы с полилиниями и в дальнейших заметках рассмотрю вопросы кодирования вершин, хранение координат вершин ломаной в виде геометрического объекта в базе данных MySQL.

  • Гость: выдает ошибку, то server responsed 404, то ymaps tags is not found в чем проблема?
  • Гость: var ml = new YMaps.YMapsML("http://webmap-blog.ru/examples/drawline/viv-xml.php"); Выдает ошибку ymap tag is not found - как ее исправить?
  • Гость: Ошибки могли возникать из-за большого количества линий, одновременно выводимых на карту (около 700). Не каждый браузер может обработать такое количество объектов. Я удалил лишние полилинии из базы и теперь все должно работать нормально
  • Гость: оно берет координаты из вашей БД, а не из той которая находиться у меня как сделать чтобы координаты брались именно с моей БД?
  • Гость: Нужно отредактировать файл config.php для соединения с базой данных $sdb_name = "localhost"; адрес сервера, как правило localhost $user_name = "root"; - имя пользователя базы данных $user_password = ""; - пароль $db_name = "gmapsbd"; имя базы данных
  • Гость: да это понятно, я в поле $db_name = «gmapsbd» - указал имя своей базы данных. просто файл viv-xml.php из строки var ml = new YMaps.YMapsML(«http://webmap-blog.ru/examples/drawline/viv-xml.php»); обращается к вашей БД, на яндексе мне сказали что YMapsML не может использоваться локально, а я делаю сайт на Apache Как мне сделать чтобы обращение было к моей БД?
  • Гость: Тут два выхода. Первый, базу данных и скрипты расположить на каком-нибудь сервере в интернет, можно бесплатном. Второй, сформировать XML-файл на локальном сервере и загрузить его на сервер в интернет и прописать путь к нему в файле viv-xml.php
  • Гость: а если нужно обновлять линии, т.е добаВЛЯЮТЬСЯ ЛИНИ ТАМ ЧЕРЕЗ ДЕНЬ, как тогда поступить? всегда загружать обновленный XML-файл в инет, тоже не выход
  • Гость: все супер! сделал, только вопрос, как сделать стрелочки направление движения маршрута как в примере: http://api.yandex.ru/maps/articles/examples/overlaypolylinewitharrows.html
  • Гость: В документации по API все написано <a href="http://api.yandex.ru/maps/articles/tasks/overlays.xml#how-to-create-polyline-with-arrows" rel="nofollow">ссылка</a>
  • Гость: Почему вы использовали в этом примере метод POST? Как будет выглядеть код при использовании метода GET?
  • Гость: Хочу задать вопрос, как возможно реализовать еще формочку ввода чтоб в файл YMaps.jQuery.post("upload.php", {coords : polyline.getPoints().join(‘;’)}); вместе с координатами уходил бы еще и некий кортеж (2-3 поля)?