API Google Maps рисуем полилинию и сохраняем ее в базе данных MySQL – продолжение

В этой заметке я продолжаю тему начатую в предыдущей записи «API Google Maps рисуем полилинию и сохраняем ее в базе данных MySQL» и здесь я рассмотрю, как сохранить нарисованную линию в базе данных, а затем вывести на карту.

В начале,  необходимо будет создать таблицу в базе данных MySQL, куда мы будем производить сохранение наших полилиний.

Сделать это можно с помощью следующего запроса:

CREATE TABLE IF NOT EXISTS `usersline` (
`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;

Мы создаем таблицу usersline, с помощью утилиты phpMyAdmin,  которая будем иметь следующую структуру:

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

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

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

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

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

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

После того, как мы создали таблицу для хранения данных необходимо написать два файла – один для соединения с нашей базой данных config.php, а другой для записи координат вершин полилинии в нашу таблицу — 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['points']);
 
$str_exp = explode("),(", $points);
 
$str_exp[0] = substr($str_exp[0], 1);
 
$str_exp[count($str_exp)-1] = substr($str_exp[count($str_exp)-1], 0, -1);
 
$points_line = implode(";", $str_exp);
 
$result = mysql_query ("INSERT INTO usersline VALUES (0, '#FF0000', 2, ' ', '$points_line')");
 
?>

Здесь мы через метод POST получаем данные о координатах вершин полилинии и с помощью различных функций для работы со строками преобразуем их в строку вида:

56.294157195782795, 43.905487060546875;56.29768165036526, 43.92316818237305;56.30168198872378, 43.937931060791016

После этого записываем наши данные в таблицу usersline, дополнительно добавляя цвет для нашей полилинии и толщину.

Теперь нам необходимо изменить код файла для рисования полилинии, чтобы координаты ее вершин передать в скрипт upload.php.

Для этого необходимо изменить функцию showPoints в файле gmap-polyline.html и после строк

document.getElementById("route").innerHTML += points[n]+'<br>’;
}

Добавить новый фрагмент кода:

GDownloadUrl("upload.php", function(data, responseCode) {
if (responseCode == 200 && data.length <= 1) {
document.getElementById("message").innerHTML = "Location added.";
}
},
"points="+points);

Здесь для передачи данных используется функция GDownloadUrl, которая может передавать параметры не только методом GET, но и POST

Смотрите ее описание в документации по адресу http://code.google.com/intl/ru/apis/maps/documentation/javascript/v2/reference.html#GDownloadUrl

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

Полный код файла  gmap-polyline.html:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"> 
  <head> 
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/> 
 
<title>API Google Maps рисуем полилинии</title> 
 
<style type="text/css"> 
 
v:* { /* Only for IE */
	behavior:url(#default#VML);
}
 
body { height: 600px; }
 
#map { position: absolute;
	top: 50px;
	left: 15px;
	width: 550px;
	height: 400px;
}
 
#descr { position: absolute;
	left: 580px;
	top: 50px;
	margin-right: 40px;
}
 
.tooltip {
	text-align: center;
	opacity: .70;
	-moz-opacity:.70;
	filter:Alpha(opacity=70);
	white-space: nowrap;
	margin: 0;
	padding: 2px 0.5ex;
	border: 1px solid #000;
	font-weight: bold;
	font-size: 9pt;
	font-family: Verdana;
	background-color: #fff;
}
 
</style> 
 
 
<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAACHCJdlgAEGcD_flKUFEmVhQlAYd20Yeej0MiKNuYPUGBnCwDThQlwUCPtCqtX3RC7LUKE-JYan3T4g"
            type="text/javascript"></script> 
 
</head> 
 
<body onload="buildMap()" onunload="GUnload()"> 
 
<div id="map"></div> 
 
<div id="descr">Нажмите на карту, чтобы установить маркеры в узлах полилинии.<br> 
Чтобы удалить существующий маркер, нажмите на маркер снова.
<p><a href="#" onclick="showPoints()">Сохранить линию</a></p> 
<div id="route"><p><strong>Координаты вершин полилинии:</strong></p></div> 
</div> 
 
<div id="message"></div>
 
<p><a href="/?p=557" title="API Google Maps рисуем полилинию и сохраняем ее в базе данных MySQL" target="_blank">Вернуться к тексту заметки</a></p> 
 
<script type="text/javascript"> 
//<![CDATA[
 
// Глобальные переменные
var mapdiv = document.getElementById("map");
var map;
var polylines = new Array();
var count = 0;
var points = new Array();
var markers = new Array();
var icon_url ="http://labs.google.com/ridefinder/images/";
var tooltip;
 
 
function addIcon(icon) { // Определяем значки для маркеров
 
 icon.shadow= icon_url + "mm_20_shadow.png";
 icon.iconSize = new GSize(12, 20);
 icon.shadowSize = new GSize(22, 20);
 icon.iconAnchor = new GPoint(6, 20);
 icon.infoWindowAnchor = new GPoint(5, 1);
}
 
 
function showTooltip(marker) { // показываем подсказки (tooltip)
 
 tooltip.innerHTML = marker.tooltip;
 tooltip.style.display = "block";
 
 // Tooltip transparency specially for IE
 if(typeof(tooltip.style.filter) == "string") {
 tooltip.style.filter = "alpha(opacity:70)";
 }
 
 var currtype = map.getCurrentMapType().getProjection();
 var point= currtype.fromLatLngToPixel(map.fromDivPixelToLatLng(new GPoint(0,0),true),map.getZoom());
 var offset= currtype.fromLatLngToPixel(marker.getLatLng(),map.getZoom());
 var anchor = marker.getIcon().iconAnchor;
 var width = marker.getIcon().iconSize.width + 6;
// var height = tooltip.clientHeight +18;
 var height = 10;
 var pos = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(offset.x - point.x - anchor.x + width, offset.y - point.y -anchor.y - height)); 
 pos.apply(tooltip);
}
 
 
function buildMap() {
 
 map = new GMap2((mapdiv), {draggableCursor:"auto", draggingCursor:"move"});
 
 // Добавляем слушатель события для белых маркеров
 GEvent.bind(map, "click", this, this.leftClick);
 
 // Добавляем div элемент для toolips
 tooltip = document.createElement("div");
 tooltip.className="tooltip";
 map.getPane(G_MAP_MARKER_PANE).appendChild(tooltip);
 
 // Определяем карту и добавляем элементы управления
 map.setCenter(new GLatLng(56.2980387, 43.9123535), 13);
 map.addControl(new GLargeMapControl()); 
 map.addControl(new GMapTypeControl()); 
 map.disableDoubleClickZoom();
} 
 
function leftClick(overlay, point) {
 
 if(point) {
 
  // Иконка для белого маркера
  var icon = new GIcon();
  icon.image = icon_url +"mm_20_white.png";
  addIcon(icon);
 
  count++;
  var w_marker = new GMarker(point, icon);
  map.addOverlay(w_marker);
  w_marker.content = count;
  markers.push(w_marker);
  points.push(point);
 
  w_marker.tooltip = "Точка "+ count;
 
  GEvent.addListener(w_marker, "mouseover", function() {
   showTooltip(w_marker);
  });
 
  GEvent.addListener(w_marker, "mouseout", function() {
   tooltip.style.display = "none";
 });
 
 if(markers.length > 1) {
 
  // Рисуем красную полилинию
  var poly = new GPolyline(points, "#ff0000", 2, 1);
  map.addOverlay(poly);
  polylines.push(poly);
 }
 
  // Слушаем событие удаление маркера
  GEvent.addListener(w_marker, "click", function() {
 
  tooltip.style.display = "none";
  // Удаляем все полилинии, прежде чем делать более короткий путь
  for(var m= 0; m < polylines.length; m++) {
   map.removeOverlay(polylines[m]);
  }
  polylines.length = 0;
  // Удаляем маркер
  for(var n = 0; n < markers.length; n++) {
 
   if(markers[n] == w_marker) {
    map.removeOverlay(markers[n]);
    break;
   }
  }
  // Уменьшаем массив маркеров и точек и настраиваем счетчик
  markers.splice(n, 1); points.splice(n, 1);
  if(markers.length == 0) {
    count = 0;
  }
   else {
    count = markers[markers.length-1].content;
  }
 
  // Рисуем короткий путь
  var newpoly = new GPolyline(points, "#ff0000", 2, 1);
  map.addOverlay(newpoly);
  polylines.push(newpoly);
  });
 }
}
 
//Выводим координаты маркеров при клике на ссылку Сохранить линию
function showPoints() {	
for (var n = 0 ; n < points.length ; n++ ) {
document.getElementById("route").innerHTML += points[n]+'<br>';
}
 
 GDownloadUrl("upload.php", function(data, responseCode) {
        if (responseCode == 200 && data.length <= 1) {         
          document.getElementById("message").innerHTML = "Location added.";
        }
      },
 
        "points="+points);
 
 
}
 
//]]>
</script> 
 
</body> 
</html>

После того как,  мы передали данные о нашей полилинии в таблицу usersline, необходимо вывести их на карту.

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

Формировать xml-файл мы будем при помощи скрипта viv-xml.php

Его код:

<?php
 
include("config.php");
 
echo '<markers>', "n";
 
$result = mysql_query("SELECT * FROM usersline");
if(mysql_num_rows($result)>0)
            {
			while ($mar = mysql_fetch_array($result))
            {
			echo '<line colour="', $mar['colour'], '" width="', $mar['width'], '" html="Полилиния-', $mar['id_line'], '"> ', "n";
			$str_exp1 = explode(";", $mar['coordinats']);
 
			for($i=0; $i<count($str_exp1); $i++)
			{
			$str_exp2 = explode(",", $str_exp1[$i]);
			echo '<point lat="', $str_exp2[0], '" lng="', $str_exp2[1], '" />', "n";
			}
 
			echo '</line>', "n";
			}
 
			}
 
			else
{
echo "<p>Линий не обнаружено!</p>";
}
 
echo '</markers>';
 
?><?php
 
include("config.php");
 
echo '<markers>', "n";
 
$result = mysql_query("SELECT * FROM usersline");
if(mysql_num_rows($result)>0)
            {
			while ($mar = mysql_fetch_array($result))
            {
			echo '<line colour="', $mar['colour'], '" width="', $mar['width'], '" html="Полилиния-', $mar['id_line'], '"> ', "n";
			$str_exp1 = explode(";", $mar['coordinats']);
 
			for($i=0; $i<count($str_exp1); $i++)
			{
			$str_exp2 = explode(",", $str_exp1[$i]);
			echo '<point lat="', $str_exp2[0], '" lng="', $str_exp2[1], '" />', "n";
			}
 
			echo '</line>', "n";
			}
 
			}
 
			else
{
echo "<p>Линий не обнаружено!</p>";
}
 
echo '</markers>';
 
?>

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

Если выполнить данный скрипт в браузере и посмотреть исходный код страницы мы увидим примерно следующее:

<markers>
<line colour="#FF0000" width="4" html="Полилиния-1">
<point lat="56.294157195782795" lng=" 43.905487060546875" />
<point lat="56.29768165036526" lng=" 43.92316818237305" />
<point lat="56.30168198872378" lng=" 43.937931060791016" />
</line>
<line colour="#008800" width="4" html="Полилиния-2">
<point lat="56.32186778153616" lng=" 43.980159759521484" />
<point lat="56.31349006825793" lng=" 43.990631103515625" />
<point lat="56.315870287350684" lng=" 44.0031623840332" />
<point lat="56.315679875282434" lng=" 44.01775360107422" />
<point lat="56.30987185111504" lng=" 44.02376174926758" />
<point lat="56.30653897945073" lng=" 44.039039611816406" />
<point lat="56.31168100253115" lng=" 44.047279357910156" />
</line>
</markers>

За вывод информации на карту будет отвечать файл viv-xml-polyline.html

Код данного файла:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html> 
<head> 
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
    <title>API Google Maps - вывод полилинии из XML-файла</title> 
<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAACHCJdlgAEGcD_flKUFEmVhQlAYd20Yeej0MiKNuYPUGBnCwDThQlwUCPtCqtX3RC7LUKE-JYan3T4g"
            type="text/javascript"></script> 
  </head> 
  <body onunload="GUnload()"> 
 
           <div id="map" style="width:800px; height: 600px"></div>       
 
    <script type="text/javascript"> 
    //<![CDATA[
 
    if (GBrowserIsCompatible()) { 
 
       // Определяем карту и добавляем элементы управления
      var map = new GMap2(document.getElementById("map"));
      map.addControl(new GLargeMapControl());
      map.addControl(new GMapTypeControl());
      map.setCenter(new GLatLng(56.2980387, 43.9123535), 13);
 
 
      // Читаем данные из XML-файла
 
      var request = GXmlHttp.create();
      request.open("GET", "viv-xml.php", true);
      request.onreadystatechange = function() {
        if (request.readyState == 4) {
          var xmlDoc = GXml.parse(request.responseText);
 
          var markers = xmlDoc.documentElement.getElementsByTagName("marker");                             
 
          // ========= Обработка полилинии ===========
          var lines = xmlDoc.documentElement.getElementsByTagName("line");
          // читаем каждую линию
          for (var a = 0; a < lines.length; a++) {
            // определяем атрибуты линии - цвет и ширину
            var colour = lines[a].getAttribute("colour");
            var width  = parseFloat(lines[a].getAttribute("width"));
            // читаем каждую вершину полилинии
            var points = lines[a].getElementsByTagName("point");
            var pts = [];
            for (var i = 0; i < points.length; i++) {
               pts[i] = new GLatLng(parseFloat(points[i].getAttribute("lat")),
                                   parseFloat(points[i].getAttribute("lng")));
            }
            map.addOverlay(new GPolyline(pts,colour,width));
          }
          // ================================================           
        }
      }
      request.send(null);
 
    }
 
    // display a warning if the browser was not compatible
    else {
      alert("К сожалению, API Карт Google, не совместимые с данным браузером");    }
 
    //]]>
    </script> 
  </body> 
 
</html>

В данном файле мы обрабатываем сгенирированный скриптом viv-xml.php xml-файл и по извлеченным из него данным рисуем полилинии.

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

Конечно, это только пример реализации процесса рисования полилинии и сохранения ее в базе данных MySQL с использованием API Google Maps.

Его можно развивать и усовершенствовать.

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

При написании заметки использовалась статья Polylines from XML

  • Гость: Спасибо Вам огромное за статью!!! У Вас отличный сайт! Все понятно даже для таких чайников как я!! )))
  • Гость: Прошу Вас, если вы знаете как можно использовать ресурс гуглерз или гуглмапс или яндекс.карты без изображенной на них карты земли, рек, дорог, улиц, домов- напишите мне. Я хочу создать вместо земли, например футбольный мяч (если это ерз), или карту своей квартиры (для игры например) нанося на него пометки и ссылки. Если кто-то знает как это сделать напишите мне zaqwsx13531@mail.ru. Огромное спасибо за оперативность.
  • Гость: ТОВАРИЩ Admin перевелите статью на Яндекс Карты, гугл уже не торт!
  • Гость: Саттья интересная, реализовал себе такую штуку. Но есть вопрос. Читаю координаты с базы рисую полилинию №1, все работает как надо. Дальше выбираю линию №2, окно обновляется но на карте все еще линия №1. Если подождать пару минут и обновить, нарисует линию №2 как и надо. Не могу понять что ограничивает время изменения линий. Работает как надо но только с интервалом в 2-3 минуты.
  • Гость: Достаточно интересно, но: 1. В JS лучше массив "впихивать" не так: pts[i] = new GLatLng(parseFloat(points[i].getAttribute("lat")), parseFloat(points[i].getAttribute("lng"))); А так: pts.push(new GLatLng(parseFloat(points[i].getAttribute("lat")), parseFloat(points[i].getAttribute("lng")))); А сейчас самое интересное: Если Вы добавляли пустой массив точек в БД, то запись добавляется. Это нужно пофиксить. И если я выполню сие действие : "map.addOverlay(new GPolyline(pts,colour,width));" полилинии, разумеется я не увижу (ошибка). =&gt; При составлении массива (читаем п.1) необходимо заранее сделать проверку в цикле for на то, что в нем содержится какое-либо содержимое. Например, я сделал так: if((points[i].getAttribute("lat")).length &gt; 10){ pts.push(new GLatLng(parseFloat(points[i].getAttribute("lat")), parseFloat(points[i].getAttribute("lng")))); } Тогда фишка с пустой строкой координат не помешает :)
  • Гость: Как у файл upload.php передать не толко координати но ещё цвет линии и припустим ее толщину (несколько параметров)?