OpenLayers загрука векторов (маркеров из файла)

Mapserver, GeoServer, MapGuide, Google и другое ПО для веб-картографии
Ответить
shs666
Новоприбывший
Сообщения: 9
Зарегистрирован: 04 май 2012, 15:23
Репутация: 0

OpenLayers загрука векторов (маркеров из файла)

Сообщение shs666 » 04 май 2012, 15:37

Всем привет, не подкинет ли кто-нибудь рабочий пример загрузки маркеров из файла (например из xml)?
Я нормалный программист но проблема моя в том, что я мало знаком с javascript, а учить его до такого уровня долго.

Или есть возможность работать с картами без помощи javascript? Может средствами Django(python)?
По мне так проще (да и быстрее) написать программу на python + Qt4, чем ковырять java.
Был бы очень признателен за помощь в этом вопросе!

Мой код слееный и скриптов собранных в гугле:

Код: Выделить всё

<!DOCTYPE HTML>
<html>
  <head>
    <title>Map</title>
    <style type="text/css">
      html, body, #basicMap {
          width: 100%;
          height: 100%;
          margin: 0;
      }
    </style>
    <script src="OpenLayers.js"></script>
    <script>
	
	var selectControl;
	var selectedFeature;
	
	function onPopupClose(evt)
	{
		selectControl.unselect(selectedFeature);
	}
	
	function onFeatureSelect(feature)
	{
		selectedFeature = feature;
		popup = new OpenLayers.Popup.FramedCloud("chicken",
			feature.geometry.getBounds().getCenterLonLat(),
			null, feature.name, null, true, onPopupClose);
		popup.panMapIfOutOfView = true;
		popup.autoSize = true;
		feature.popup = popup;
		map.addPopup(popup);
	}
	
	function onFeatureUnselect(feature)
	{
		map.removePopup(feature.popup);
		feature.popup.destroy();
		feature.popup = null;
	}

	function init()
	{
		map = new OpenLayers.Map("basicMap");
        var mapnik         = new OpenLayers.Layer.OSM();
        var fromProjection = new OpenLayers.Projection("EPSG:4326");   // Transform from WGS 1984
        var toProjection   = new OpenLayers.Projection("EPSG:900913"); // to Spherical Mercator Projection
        var position       = new OpenLayers.LonLat(55,55).transform( fromProjection, toProjection);
        var zoom           = 3; 
		
		map.addLayer(mapnik);
		map.setCenter(position, zoom);
		
		var vectorLayer = new OpenLayers.Layer.Vector("Vectors");
		var point = new OpenLayers.Geometry.Point(55, 55).transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"));
		var feature = new OpenLayers.Feature.Vector(point, {some:'data'}, {externalGraphic: 'img/marker.png', graphicHeight: 21, graphicWidth: 16});
		feature.name = "<b>Name: </b>Vasya<br><b>Familiya: </b>Pupkin</br>";
		
		selectControl = new OpenLayers.Control.SelectFeature(vectorLayer,
		{
			onSelect: onFeatureSelect,
			onUnselect: onFeatureUnselect 
		});

		vectorLayer.addFeatures([feature]);

		map.addLayer(vectorLayer);
		map.addControl(selectControl);
		
		selectControl.activate();
		

	}
	
    </script>
  </head>
  <body onload="init();">
    <div id="basicMap"></div>
  </body>
</html>

Аватара пользователя
Denis Rykov
Гуру
Сообщения: 3376
Зарегистрирован: 11 апр 2008, 21:09
Репутация: 529
Ваше звание: Author
Контактная информация:

Re: OpenLayers загрука векторов (маркеров из файла)

Сообщение Denis Rykov » 04 май 2012, 18:10

Не понял вас, вам нужно web приложение или нет? Если да, то каким боком в тексте фигурирует qt? Насчет загрузки данных в ol - все очень просто, если данные находятся в формате, который понимает ol, то можно обойтись без велосипедов, если нет - приведите описание структуры ваших данных, посмотрим.

[ Сообщение с мобильного устройства ]
Spatial is now, more than ever, just another column- The Geometry Column.

shs666
Новоприбывший
Сообщения: 9
Зарегистрирован: 04 май 2012, 15:23
Репутация: 0

Re: OpenLayers загрука векторов (маркеров из файла)

Сообщение shs666 » 04 май 2012, 18:26

Спасибо за отклик.
Да, нужно web приложение.

Вот пример данных, которые возвращает php скрипт http://127.0.0.1/genxml.php

Код: Выделить всё

<?xml version="1.0"?>
<markers>
  <marker>
     <id>MARKER-1</id>
    <name>Nikolay Ivanov</name>
    <address>near Ghumaghumalu Restaurant, Marripalem, Visakhapatnam</address>
    <lat>17.74033553</lat>
    <lng>83.25067267</lng>
  </marker>
  <marker>
  <id>MARKER-2</id>
    <name>Alexey Petrov</name>
    <address>near Viswa Teja School, Thatichetlapalem, Visakhapatnam</address>
    <lat>17.73254774</lat>
    <lng>83.29195094</lng>
  </marker>
</markers>
По сути можно и не в XML. Если понадобится могу и в другом виде инфу генерировать, какая удобнее.

Задача состоит в том, что скрипт должен:
1) каждые 30 секунд делать запрос к http://127.0.0.1/genxml.php (через ajax наверное)
2) получать инфу от туда и отрисовывать или перемещать маркеры по обновившимся координатам
3) Привязывать к каждому маркеру popup информацию (name, address).

Вот такие вот дела...

Аватара пользователя
Denis Rykov
Гуру
Сообщения: 3376
Зарегистрирован: 11 апр 2008, 21:09
Репутация: 529
Ваше звание: Author
Контактная информация:

Re: OpenLayers загрука векторов (маркеров из файла)

Сообщение Denis Rykov » 05 май 2012, 10:52

Лучше конечно же использовать стандартные форматы, например, GeoJSON, чтобы не писать собственных парсеров. Но если вам проще сформировать xml предложенной структуры, то и в этом случае нет ничего сложного. Напишем формат, извлекающий объекты OpenLayers.Feature.Vector из файлов, предложенной структуры:

Код: Выделить всё


OpenLayers.Format.shs666 = OpenLayers.Class(OpenLayers.Format.XML, {

geons: "*",

createGeometryFromItem: function(item) {
var lat = this.getElementsByTagNameNS(item, this.geons, 'lat');
var lon = this.getElementsByTagNameNS(item, this.geons, 'lng');

if (lat.length > 0 && lon.length > 0) {
var location;
location = [parseFloat(lat[0].firstChild.nodeValue),
parseFloat(lon[0].firstChild.nodeValue)];

var geometry = new OpenLayers.Geometry.Point(location[1], location[0]);

if (geometry && this.internalProjection && this.externalProjection) {
geometry.transform(this.externalProjection,
this.internalProjection);
}
}

return geometry;
},

createFeatureFromItem: function(item) {
var geometry = this.createGeometryFromItem(item);

var id = this._getChildValue(item, "*", "id", null);
var name = this._getChildValue(item, "*", "name", null);
var address = this._getChildValue(item, "*", "address", null);

var data = {
"name": name,
"address": address
};
var feature = new OpenLayers.Feature.Vector(geometry, data);
feature.fid = id;
return feature;
},

_getChildValue: function(node, nsuri, name, def) {
var value;
var eles = this.getElementsByTagNameNS(node, nsuri, name);
if(eles && eles[0] && eles[0].firstChild
&& eles[0].firstChild.nodeValue) {
value = this.getChildValue(eles[0]);
} else {
value = (def == undefined) ? "" : def;
}
return value;
},

read: function(doc) {
if (typeof doc == "string") {
doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]);
}

var itemlist = this.getElementsByTagNameNS(doc, '*', 'marker');

var numItems = itemlist.length;
var features = [];
for(var i=0; i<numItems; i++) {
features = this.createFeatureFromItem(itemlist);
}
return features;
},

CLASS_NAME: "OpenLayers.Format.shs666"
});

Чтобы слой периодически перерисовывался воспользуемся стратегией OpenLayers.Strategy.Refresh. Описание слоя будет выглядеть следующим образом:

Код: Выделить всё

xmllayer = new OpenLayers.Layer.Vector("XML", {
projection: new OpenLayers.Projection('EPSG:4326'),
strategies: [new OpenLayers.Strategy.Fixed(), new OpenLayers.Strategy.Refresh({interval: 1000})],
protocol: new OpenLayers.Protocol.HTTP({
url: "./data/test.xml",
format: new OpenLayers.Format.shs666()
})
});

Пример можно посмотреть здесь. Если открыть фаербаг, то увидите, что каждую секнду слой запрашивается заново.
Spatial is now, more than ever, just another column- The Geometry Column.

shs666
Новоприбывший
Сообщения: 9
Зарегистрирован: 04 май 2012, 15:23
Репутация: 0

Re: OpenLayers загрука векторов (маркеров из файла)

Сообщение shs666 » 05 май 2012, 11:18

Пример работает превосходно!
Последняя деталь - каким образом popup инфо к маркерам?

Аватара пользователя
Denis Rykov
Гуру
Сообщения: 3376
Зарегистрирован: 11 апр 2008, 21:09
Репутация: 529
Ваше звание: Author
Контактная информация:

Re: OpenLayers загрука векторов (маркеров из файла)

Сообщение Denis Rykov » 05 май 2012, 12:33

shs666 писал(а):Последняя деталь - каким образом popup инфо к маркерам?
Вы же сами в первом посте написали. А обратиться к атрибутике фичи можно так:

Код: Выделить всё

feature.attributes.address
Spatial is now, more than ever, just another column- The Geometry Column.

shs666
Новоприбывший
Сообщения: 9
Зарегистрирован: 04 май 2012, 15:23
Репутация: 0

Re: OpenLayers загрука векторов (маркеров из файла)

Сообщение shs666 » 05 май 2012, 12:51

Разобрался, спасибо. Буду ковырять дальше, если возникнут допвопросы буду спрашивать :P

shs666
Новоприбывший
Сообщения: 9
Зарегистрирован: 04 май 2012, 15:23
Репутация: 0

Re: OpenLayers загрука векторов (маркеров из файла)

Сообщение shs666 » 05 май 2012, 15:35

Что-то не получается Popups прикрутить. Сказывается слабое знание скриптинга.

Код:

Код: Выделить всё

	var selectControl;
	var selectedFeature;
   
   function onPopupClose(evt)
   {
      selectControl.unselect(selectedFeature);
   }
   
   function onFeatureSelect(feature)
   {
      selectedFeature = feature;
      popup = new OpenLayers.Popup.FramedCloud("chicken",
         feature.geometry.getBounds().getCenterLonLat(),
         null, feature.name, null, true, onPopupClose);
      popup.panMapIfOutOfView = true;
      popup.autoSize = true;
      feature.popup = popup;
      map.addPopup(popup);
   }
   
   function onFeatureUnselect(feature)
   {
      map.removePopup(feature.popup);
      feature.popup.destroy();
      feature.popup = null;
   }
   
        var lon = 28.14985,
            lat = 49.89785,
            zoom = 10,
            epsg4326 = new OpenLayers.Projection('EPSG:4326'),
            epsg900913 = new OpenLayers.Projection('EPSG:900913');

        function init(){
            map = new OpenLayers.Map('map', {
                units: 'm',
                //maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
                //maxResolution: 156543.0399,
                numZoomLevels: 19,
                controls: [
                    new OpenLayers.Control.Navigation(),
                    new OpenLayers.Control.ScaleLine(),
                    new OpenLayers.Control.MousePosition(),
                    new OpenLayers.Control.LayerSwitcher()
                ],
                projection: epsg900913,
                displayProjection: epsg4326 //Is used for displaying coordinates in appropriate CRS by MousePosition control
            });


            var lay_osm = new OpenLayers.Layer.OSM('OSM');

            var styleMap = new OpenLayers.StyleMap(OpenLayers.Util.applyDefaults(
                {fillColor: "green", fillOpacity: 1, strokeColor: "black", pointRadius: 12},
                OpenLayers.Feature.Vector.style["default"])
            );

            xmllayer = new OpenLayers.Layer.Vector("Маркеры", {
                projection: epsg4326,
                styleMap: styleMap,
                strategies: [new OpenLayers.Strategy.Fixed(), new OpenLayers.Strategy.Refresh({interval: 1000})],
                protocol: new OpenLayers.Protocol.HTTP({
                    url: "./test.xml",
                    format: new OpenLayers.Format.shs666()
                })
            });
			
			selectControl = new OpenLayers.Control.SelectFeature(xmllayer,
			{
				onSelect: onFeatureSelect,
				onUnselect: onFeatureUnselect
			});
			
            map.addLayers([lay_osm, xmllayer]);
            map.setCenter(new OpenLayers.LonLat(lon, lat).transform(epsg4326, epsg900913), zoom);
			
			selectControl.activate();
        }
shs666.js не менял.

Карта с маркерами грузится, а popup не работает.

В Firebug ошибка:

Код: Выделить всё

this.map is null
OpenLayers.js Line 1351

Аватара пользователя
Denis Rykov
Гуру
Сообщения: 3376
Зарегистрирован: 11 апр 2008, 21:09
Репутация: 529
Ваше звание: Author
Контактная информация:

Re: OpenLayers загрука векторов (маркеров из файла)

Сообщение Denis Rykov » 05 май 2012, 21:41

Обновил пример - посмотрите. В вашей ситуации вы столкнетесь с проблемой - при открытом попапе происходит обновление объектов на карте (OpenLayers.Strategy.Refresh), а так как попап привязан к конкретному объекту, то при попытке его закрыть будете получать ошибку, так как фича, которой он принадлежит уже не существует на карте.
Spatial is now, more than ever, just another column- The Geometry Column.

shs666
Новоприбывший
Сообщения: 9
Зарегистрирован: 04 май 2012, 15:23
Репутация: 0

Re: OpenLayers загрука векторов (маркеров из файла)

Сообщение shs666 » 05 май 2012, 22:35

Тоесть получается popup уже никак не закрыть? Или же можно это дело можно в виде exception'а оформить? Наподобие - Если ошибка "layer is null" , то удалить слой и отрисовать заново.

shs666
Новоприбывший
Сообщения: 9
Зарегистрирован: 04 май 2012, 15:23
Репутация: 0

Re: OpenLayers загрука векторов (маркеров из файла)

Сообщение shs666 » 08 май 2012, 11:34

Сделал данные в "родном" формате.
Теперь заместо скрипта gen_xml.php данные генерирует Django в формате geojson:
http://127.0.0.1/get_markers

Код: Выделить всё

[{"pk": 1, 
"model": "gpsmon.markers", 
				"fields": {
						"last_update": null, 
						"data1": "free", 
						"beacon_id": "SH001", 
						"data10": null, 
						"data5": null, 
						"lat": 52.111, 
						"driver_name": 
						"Vasya Pupkin", 
						"data9": null, 
						"data8": null, 
						"device": "Device0x5", 
						"data4": null, 
						"lng": 57.111, 
						"data6": null, 
						"speed": 1.111, 
						"data7": null, 
						"data3": null, 
						"data2": null}}, 
{"pk": 2, "model": "gpsmon.markers", 
				"fields": {
						"last_update": null,
						"data1": "free", 
						"beacon_id": "SH002", 
						"data10": null,
						"data5": null,
						"lat": 53.111, 
						"driver_name": 
						"Vasya Pupkin2", 
						"data9": null, 
						"data8": null, 
						"device": "Device0x6",
						"data4": null,
						"lng": 57.111,
						"data6": null,
						"speed": 1.111,
						"data7": null,
						"data3": null,
						"data2": null}}]
Можно пример как эти данные использовать для вывода маркеров на карте?

P. S. информацию содержащую 'null' выводить не нужно. А все остальное нужно в popup'e.

Аватара пользователя
Denis Rykov
Гуру
Сообщения: 3376
Зарегистрирован: 11 апр 2008, 21:09
Репутация: 529
Ваше звание: Author
Контактная информация:

Re: OpenLayers загрука векторов (маркеров из файла)

Сообщение Denis Rykov » 09 май 2012, 13:52

shs666 писал(а):Тоесть получается popup уже никак не закрыть? Или же можно это дело можно в виде exception'а оформить? Наподобие - Если ошибка "layer is null" , то удалить слой и отрисовать заново.
При обновлении слоя информация, содержащаяся в открытом попапе может не соответствовать той, что пришла к объекту при последнем обновлении, поэтому как мне кажется логичным будет при перерисовке слоя удалять открытый попап, для этого переопределим метод refresh стратегии OpenLayers.Strategy.Refresh:

Код: Выделить всё

OpenLayers.Strategy.Refresh.prototype.refresh = function() {
if (this.layer && this.layer.refresh && typeof this.layer.refresh == "function") {
this.layer.refresh({force: this.force});
if (map.popups.length > 0){
map.popups[0].destroy();
}
}
}

Обновил пример.
Spatial is now, more than ever, just another column- The Geometry Column.

Аватара пользователя
Denis Rykov
Гуру
Сообщения: 3376
Зарегистрирован: 11 апр 2008, 21:09
Репутация: 529
Ваше звание: Author
Контактная информация:

Re: OpenLayers загрука векторов (маркеров из файла)

Сообщение Denis Rykov » 09 май 2012, 14:05

shs666 писал(а):Сделал данные в "родном" формате.
Теперь заместо скрипта gen_xml.php данные генерирует Django в формате geojson:
http://127.0.0.1/get_markers

Код: Выделить всё

[{"pk": 1, 
"model": "gpsmon.markers", 
				"fields": {
						"last_update": null, 
						"data1": "free", 
						"beacon_id": "SH001", 
						"data10": null, 
						"data5": null, 
						"lat": 52.111, 
						"driver_name": 
						"Vasya Pupkin", 
						"data9": null, 
						"data8": null, 
						"device": "Device0x5", 
						"data4": null, 
						"lng": 57.111, 
						"data6": null, 
						"speed": 1.111, 
						"data7": null, 
						"data3": null, 
						"data2": null}}, 
{"pk": 2, "model": "gpsmon.markers", 
				"fields": {
						"last_update": null,
						"data1": "free", 
						"beacon_id": "SH002", 
						"data10": null,
						"data5": null,
						"lat": 53.111, 
						"driver_name": 
						"Vasya Pupkin2", 
						"data9": null, 
						"data8": null, 
						"device": "Device0x6",
						"data4": null,
						"lng": 57.111,
						"data6": null,
						"speed": 1.111,
						"data7": null,
						"data3": null,
						"data2": null}}]
Можно пример как эти данные использовать для вывода маркеров на карте?

P. S. информацию содержащую 'null' выводить не нужно. А все остальное нужно в popup'e.
Можно, толко ваш GeoJSON невалидный и ничего вы с ним не сделаете, валидный GeoJSON должен иметь такую структуру:

Код: Выделить всё

{
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "properties": { "id": 1, "driver_name": "Vasya Pupkin" }, "geometry": { "type": "Point", "coordinates": [ 57.111, 52.111 ] } }
,
{ "type": "Feature", "properties": { "id": 2, "driver_name": "Vasya Pupkin2" }, "geometry": { "type": "Point", "coordinates": [ 57.111, 53.111 ] } }
]
}
Spatial is now, more than ever, just another column- The Geometry Column.

shs666
Новоприбывший
Сообщения: 9
Зарегистрирован: 04 май 2012, 15:23
Репутация: 0

Re: OpenLayers загрука векторов (маркеров из файла)

Сообщение shs666 » 09 май 2012, 16:34

Спасибо за решение проблемы с popup.

Теперь geojson генерируется корректный:

Код: Выделить всё

{ "type": "FeatureCollection","features": [
	{ "type": "Feature", "properties": { "id": 1, "Name": "Vasya Pupkin", "speed": 1.111000, "data1": "stay"}, "geometry": { "type": "Point", "coordinates": [ 52.111000, 57.111000 ] } },
	{ "type": "Feature", "properties": { "id": 2, "Name": "Vasya Pupkin2", "speed": 2.22200, "data1": "moving"}, "geometry": { "type": "Point", "coordinates": [ 53.111000, 57.111000 ] } }
]}
В заключении хотелось бы увидеть код который работает без XML парсинга с родным GeoJson форматом (который привел я или Вы в своем последнем посте). Чтобы намотать на ус и до конца врубиться в данную тему :)

Аватара пользователя
Denis Rykov
Гуру
Сообщения: 3376
Зарегистрирован: 11 апр 2008, 21:09
Репутация: 529
Ваше звание: Author
Контактная информация:

Re: OpenLayers загрука векторов (маркеров из файла)

Сообщение Denis Rykov » 09 май 2012, 17:40

Никаких сложностей, просто используете нужный формат и всё, пример обновил.
Spatial is now, more than ever, just another column- The Geometry Column.

Ответить

Вернуться в «Веб-картография»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя