Сейчас на рынке много предложений по продаже мобильных устройств, предназначенных для контроля движущихся объектов или трекеров. В большинстве из них есть функция передачи информации по GPRS на любой заданный веб-адрес через определенный интервал времени. Чаще всего формат передачи данных разный. Поэтому мы не будем рассматривать вопрос загрузки данных с трекера в базу. Предположим данные есть и мы хотим приступить к созданию сервиса мониторинга транспорта. Основу такой системы образуют возможности:
-выбор карты и ее отображение
-отображение точки или картинки и подписи к ней
-отображение полигона и его редактирование
-отображение линии и ее редактирование
-отображение информации связной с полигонами, линиями, точками (всплывающие подсказки)
-немного математики (подсчет пройденного пути, площадь полигона, принадлежность точки полигону)
Все эти функции легко реализовать с помощью OpenLayers, библиотеки на JavaScript.

Выбор карты и ее отображение
Для этого на вашей страничке нужно создать элемент div c нужными размерами. В нем и будет отображаться карта. Пример:
Подключить OpenLayers:
Создать глобальную переменную map, в которой будет храниться объект карты. Создать вызов функции на событие загрузки страницы, в которой будет код непосредственного создания карты. Пример:
Описать функцию LoadMap:
На сайте проекта openlayers можно найти много примеров, около двухсот. Пример визуализации карты из заданного сервиса, можно увидеть здесь. Большинство решаемых задач в статье эти примеры покрывают. В представленном коде отсутствует присоединение карт google и yandex, для работы этих карт нужны ключи. Вы должны зарегистрироваться, получить ключ доступа к сервису и только после этого можно подсоединяться к этим сервисам. Результат кода выше:
Отображение точки или картинки и подписи к ней
Создаем слои, которые будет хранить наши объекты(точки и картинки).
Слои созданы, создаем функции которые будут работать со слоями.
Результат:
Добавилось только одно изображение потому, что вызов функции был с одинаковыми идентификаторами изображений. Объект сместился, название было изменено на новое.
Отображение полигона �� его редактирование
Функция создания полигона:
Пример вызова функции прорисовки полигона:
Редактирование в OpenLayrs осуществляется с помощью OpenLayers.Control.ModifyFeature. Нужно создать экземпляр этого класса указав слой объекты которого нужно модифицировать:
Каждая вершина полигона в момент редактирования обозначается точкой и в силу того, что полигон мы разместили на слое для точек, к ним был применен стиль этого слоя. Результат: подписи «undefined» у вершин полигона. Это приме того, что для каждого типа объектов лучше создавать отдельные слои. Пример отображения режима редактирования:
Выход из режима редактирования:
Отображение линии и ее редактирование
Как было уже сказано, полигон создается из линии, таким образом в функции AddPoly нужно изменить одну строку:
на
Процесс редактирование ничем не отличается.
Всплывающие подсказки
Для реализации всплывающей подсказки нужно добавить на карту обработчик событий, который представляет собой экземпляр класса: OpenLayers.Control.SelectFeature.
После этого будет происходить обработка нажатий на объекты слоев. Точки будут увеличиваться в размере, картинки поворачиваться на 45 градусов. Создаем обработчик события выделения точки:
Подсчет пройденного пути, площадь полигона, принадлежность точки полигону
Подсчет пройденного пути
площадь полигона
принадлежность точки полигону
Результат всех предыдущих действий можно увидеть на странице: ссылка
В заключение отмечу, что многое компании уже сделали свои трекеры на OpenLayers это дешево и просто. Документацию по OpenLayers можно найти тут.
-выбор карты и ее отображение
-отображение точки или картинки и подписи к ней
-отображение полигона и его редактирование
-отображение линии и ее редактирование
-отображение информации связной с полигонами, линиями, точками (всплывающие подсказки)
-немного математики (подсчет пройденного пути, площадь полигона, принадлежность точки полигону)
Все эти функции легко реализовать с помощью OpenLayers, библиотеки на JavaScript.

Выбор карты и ее отображение
Для этого на вашей страничке нужно создать элемент div c нужными размерами. В нем и будет отображаться карта. Пример:
div id="map" style="position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px;"
Подключить OpenLayers:
script type="text/javascript" src="Scripts/OpenLayers.js"
Создать глобальную переменную map, в которой будет храниться объект карты. Создать вызов функции на событие загрузки страницы, в которой будет код непосредственного создания карты. Пример:
body onload="LoadMap()"
Описать функцию LoadMap:
//Границы задаются для проекции EPSG:900913. var maxExtent = new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508); var restrictedExtent = maxExtent.clone(); var maxResolution = 156543.0339; //Отображаться карта будет в проекции EPSG:4326. var options = { projection: new OpenLayers.Projection("EPSG:900913"), displayProjection: new OpenLayers.Projection("EPSG:4326"), numZoomLevels: 18, maxResolution: maxResolution, maxExtent: maxExtent, restrictedExtent: restrictedExtent }; //Создаем карту map = new OpenLayers.Map('map', options); // Создаем слои-карты VirtualEarth var veroad = new OpenLayers.Layer.VirtualEarth("Virtual Earth Roads", { 'type': VEMapStyle.Road, sphericalMercator: true }); var veaer = new OpenLayers.Layer.VirtualEarth("Virtual Earth Aerial", { 'type': VEMapStyle.Aerial, hericalMercator: true }); var vehyb = new OpenLayers.Layer.VirtualEarth("Virtual Earth Hybrid", { 'type': VEMapStyle.Hybrid, sphericalMercator: true }); // Создаем слои-карты OpenStreet var mapnik = new OpenLayers.Layer.OSM(); //Добавляем подсказку масштаба карты и позици курсора map.addControl(new OpenLayers.Control.ScaleLine()); map.addControl(new OpenLayers.Control.MousePosition()); //Складываем созданные слои в объект OpenLayers.Map map.addLayers([ mapnik, veroad, veaer, vehyb]); //Добавляем панель управления слоями map.addControl(new OpenLayers.Control.LayerSwitcher()); //Создаем точку на которую будет центрироваться карта при старте var point0 = new OpenLayers.Geometry.Point(37.600328, 55.574624); //Помним что карта отображается в одной проекции, а с данными работает в другой проекции. point0.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")); //Выполняем центрирование карты на точку с масштабом 9. По умолчанию их 15. map.setCenter(new OpenLayers.LonLat(point0.x, point0.y), 9); }
На сайте проекта openlayers можно найти много примеров, около двухсот. Пример визуализации карты из заданного сервиса, можно увидеть здесь. Большинство решаемых задач в статье эти примеры покрывают. В представленном коде отсутствует присоединение карт google и yandex, для работы этих карт нужны ключи. Вы должны зарегистрироваться, получить ключ доступа к сервису и только после этого можно подсоединяться к этим сервисам. Результат кода выше:
Отображение точки или картинки и подписи к ней
Создаем слои, которые будет хранить наши объекты(точки и картинки).
//Создаем объект стиля отображения картинок. Указываем параметры ширены, высоты, сдвига по вертикале относительно точки, подпись(${} - это объявление параметра, можно выводить константу для всех точек), url к графику, размер шрифта. var styleImage = new OpenLayers.Style( { graphicWidth: 21, graphicHeight: 25, graphicYOffset: -28, label: "${label}", externalGraphic: "http://www.openlayers.org/dev/img/marker.png", fontSize: 12 }); //labelYOffset - сдвиг текста по вертикале относительно точки var stylePoint = new OpenLayers.Style( { pointRadius: 5, strokeColor: "red", strokeWidth: 2, fillColor: "lime", labelYOffset: -16, label: "${label}", fontSize: 16 }); //Создаем слой для точек. В свойстве styleMap указываем как отображать в обычном случае. Свойство select будет применено после выбора элемента. var vectorPoint = new OpenLayers.Layer.Vector("Точки", { styleMap: new OpenLayers.StyleMap( { "default": stylePoint, "select": { pointRadius: 20} }) }); //В отличие от слоя с точками, где выделение объекта взывает увеличение радиуса точки, на слое с картинками будет их поворот на 45 градусов var vectorImage = new OpenLayers.Layer.Vector("Картинки", { styleMap: new OpenLayers.StyleMap( { "default": styleImage, "select": { rotation: 45} }) }); //Складываем слои на карту map.addLayer(vectorImage ); map.addLayer(vectorPoint );
Слои созданы, создаем функции которые будут работать со слоями.
//Функция добавляет изображение с подписью. Аргументы: долгота, широта, подпись, уникальный идентификатор, слой. В случае, если объект уже есть функция сдвигает его в новое положение. function addImg(lon,lat,title,ident, layr){ var ttt = new OpenLayers.LonLat(parseFloat(lon), parseFloat(lat)); ttt.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")); // features-массив объектов на карте. Объект может быть например: точкой, полигоном, кривой, изображением for (var k = 0; k < layr.features.length; k++) { // У объектов features есть атрибуты, как предопределенные так и добавленные пользователем if(layr.features[k].attributes.ImgId==ident) { // move - функция перемещения объекта в данную точку layr.features[k].move(ttt); layr.features[k].attributes.label=title; return false; } } var point0 = new OpenLayers.Geometry.Point(parseFloat(lon), parseFloat(lat)); point0.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")); //Для создание объекта Feature использовался класс OpenLayers.Feature.Vector layr.addFeatures(new OpenLayers.Feature.Vector(point0, { label: title, name: title, ImgId: ident })); } function addPoint(lon,lat,title,ident){ var ttt = new OpenLayers.LonLat(parseFloat(lon), parseFloat(lat)); ttt.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")); for (var k = 0; k < map.layers[5].features.length; k++) { if(map.layers[5].features[k].attributes.PointId==ident) { map.layers[5].features[k].move(ttt); map.layers[5].features[k].attributes.label=title; return false; } } var point0 = new OpenLayers.Geometry.Point(parseFloat(lon), parseFloat(lat)); point0.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")); map.layers[5].addFeatures(new OpenLayers.Feature.Vector(point0, { label: title, name: title, PointId: ident })); } </code> Теперь осталось выполнить добавление точек и изображений: <code> addPoint(37,55.5,'Точка 1','1',map.layers[4]); addPoint(37,55.1,'Точка 2','2',map.layers[4]); addImg(37,55.6,'Изображение 1','2',map.layers[5]); addImg(37,55.9,'Изображение 2','2',map.layers[5]);
Результат:
Добавилось только одно изображение потому, что вызов функции был с одинаковыми идентификаторами изображений. Объект сместился, название было изменено на новое.
Отображение полигона �� его редактирование
Функция создания полигона:
//Предполагаемый форма данных: координаты разделены точкой с запятой, долгота с широтой разделены пробелом function addPoly(data,title,ident,layr){ var featuress = Array(); var coords = data.split(';'); for (var i = 0; i < coords.length; i++) { var d = coords[i].split(' '); var ttt = new OpenLayers.LonLat(parseFloat(d[0]), parseFloat(d[1])); var point0 = new OpenLayers.Geometry.Point(ttt.lon, ttt.lat); point0.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")); featuress.push(point0); } //Массив точек порождает линию, из нее создается полигон var linearRing2 = new OpenLayers.Geometry.LinearRing(featuress); var polygonFeature2 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Polygon([linearRing2]), { label: title, PolyID: ident }); layr.addFeatures(polygonFeature2); }
Пример вызова функции прорисовки полигона:
addPoly('37 55.9;37.5 55.4;37 55','Полигон','1',map.layers[5]);
Редактирование в OpenLayrs осуществляется с помощью OpenLayers.Control.ModifyFeature. Нужно создать экземпляр этого класса указав слой объекты которого нужно модифицировать:
var modef = new OpenLayers.Control.ModifyFeature(map.layers[5]) modef.clickout = false; modef.toggle = false; modef.standalone = true; map.addControls([ modef]); modef.activate(); //Выбираем созданный полигон modef.selectFeature(map.layers[5].features[2]); //Получаем центр полигона var centr = map.layers[5].features[2].geometry.getCentroid() //Карту центрируем по полученной точке map.setCenter(new OpenLayers.LonLat(centr.x, centr.y));
Каждая вершина полигона в момент редактирования обозначается точкой и в силу того, что полигон мы разместили на слое для точек, к ним был применен стиль этого слоя. Результат: подписи «undefined» у вершин полигона. Это приме того, что для каждого типа объектов лучше создавать отдельные слои. Пример отображения режима редактирования:
Выход из режима редактирования:
modef.deactivate();
Отображение линии и ее редактирование
Как было уже сказано, полигон создается из линии, таким образом в функции AddPoly нужно изменить одну строку:
layr.addFeatures(polygonFeature2);
на
layr.addFeatures(linearRing2 );
Процесс редактирование ничем не отличается.
Всплывающие подсказки
Для реализации всплывающей подсказки нужно добавить на карту обработчик событий, который представляет собой экземпляр класса: OpenLayers.Control.SelectFeature.
var selectControl = new OpenLayers.Control.SelectFeature([map.layers[5]]); map.addControls([selectControl], { clickout: true, toggle: false, multiple: false, hover: true, toggleKey: "ctrlKey", multipleKey: "shiftKey" }); selectControl.activate();
После этого будет происходить обработка нажатий на объекты слоев. Точки будут увеличиваться в размере, картинки поворачиваться на 45 градусов. Создаем обработчик события выделения точки:
//Событие on - это событие выделения map.layers[5].events.on( { "featureselected": function (e) { var HTMLcontent; var point //Здесь можно генерировать любой контент HTMLcontent = 'table style="width: 100%;" tr td Информация об объекте td tr table '; //getCentroid() - получить центр фигуры, в данном случае лишнее, но это унифицированный способ получения места всплытия подсказки point = new OpenLayers.LonLat(e.feature.geometry.getCentroid().x, e.feature.geometry.getCentroid().y); //OpenLayers.Popup.AnchoredBubble - всплывающий прямоугольник, есть другие варианты в OpenLayers.Popup var popup = new OpenLayers.Popup.AnchoredBubble("SDVegetationInfo", point, new OpenLayers.Size(100, 100), HTMLcontent, null, false); popup.opacity = 0.9; popup.autoSize = true; popup.setBackgroundColor("#bcd2bb"); //добавление на карту map.addPopup(popup, true); } // когда выделение убрано, через секунду окно погаснет , "featureunselected": function (e) { setTimeout('if(map.popups.length - 1>-1){map.removePopup(map.popups[map.popups.length - 1]);}', 1000); } });
Подсчет пройденного пути, площадь полигона, принадлежность точки полигону
Подсчет пройденного пути
map.layers[4].features[2].feature.geometry.getLength()
площадь полигона
map.layers[4].features[2].feature.geometry.getArea()
принадлежность точки полигону
map.layers[4].features[2].containsPoint(map.layers[4].features[0])
Результат всех предыдущих действий можно увидеть на странице: ссылка
В заключение отмечу, что многое компании уже сделали свои трекеры на OpenLayers это дешево и просто. Документацию по OpenLayers можно найти тут.