Страница 1 из 1
OpenLayers загрука векторов (маркеров из файла)
Добавлено: 04 май 2012, 15:37
shs666
Всем привет, не подкинет ли кто-нибудь рабочий пример загрузки маркеров из файла (например из 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>
Re: OpenLayers загрука векторов (маркеров из файла)
Добавлено: 04 май 2012, 18:10
Denis Rykov
Не понял вас, вам нужно web приложение или нет? Если да, то каким боком в тексте фигурирует qt? Насчет загрузки данных в ol - все очень просто, если данные находятся в формате, который понимает ol, то можно обойтись без велосипедов, если нет - приведите описание структуры ваших данных, посмотрим.
[ Сообщение с мобильного устройства ]
Re: OpenLayers загрука векторов (маркеров из файла)
Добавлено: 04 май 2012, 18:26
shs666
Спасибо за отклик.
Да, нужно 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).
Вот такие вот дела...
Re: OpenLayers загрука векторов (маркеров из файла)
Добавлено: 05 май 2012, 10:52
Denis Rykov
Лучше конечно же использовать стандартные форматы, например,
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()
})
});
Пример можно посмотреть
здесь. Если открыть фаербаг, то увидите, что каждую секнду слой запрашивается заново.
Re: OpenLayers загрука векторов (маркеров из файла)
Добавлено: 05 май 2012, 11:18
shs666
Пример работает превосходно!
Последняя деталь - каким образом popup инфо к маркерам?
Re: OpenLayers загрука векторов (маркеров из файла)
Добавлено: 05 май 2012, 12:33
Denis Rykov
shs666 писал(а):Последняя деталь - каким образом popup инфо к маркерам?
Вы же сами в первом посте написали. А обратиться к атрибутике фичи можно так:
Re: OpenLayers загрука векторов (маркеров из файла)
Добавлено: 05 май 2012, 12:51
shs666
Разобрался, спасибо. Буду ковырять дальше, если возникнут допвопросы буду спрашивать

Re: OpenLayers загрука векторов (маркеров из файла)
Добавлено: 05 май 2012, 15:35
shs666
Что-то не получается 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 ошибка:
Re: OpenLayers загрука векторов (маркеров из файла)
Добавлено: 05 май 2012, 21:41
Denis Rykov
Обновил пример - посмотрите. В вашей ситуации вы столкнетесь с проблемой - при открытом попапе происходит обновление объектов на карте (OpenLayers.Strategy.Refresh), а так как попап привязан к конкретному объекту, то при попытке его закрыть будете получать ошибку, так как фича, которой он принадлежит уже не существует на карте.
Re: OpenLayers загрука векторов (маркеров из файла)
Добавлено: 05 май 2012, 22:35
shs666
Тоесть получается popup уже никак не закрыть? Или же можно это дело можно в виде exception'а оформить? Наподобие - Если ошибка "layer is null" , то удалить слой и отрисовать заново.
Re: OpenLayers загрука векторов (маркеров из файла)
Добавлено: 08 май 2012, 11:34
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.
Re: OpenLayers загрука векторов (маркеров из файла)
Добавлено: 09 май 2012, 13:52
Denis Rykov
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();
}
}
}
Обновил
пример.
Re: OpenLayers загрука векторов (маркеров из файла)
Добавлено: 09 май 2012, 14:05
Denis Rykov
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 ] } }
]
}
Re: OpenLayers загрука векторов (маркеров из файла)
Добавлено: 09 май 2012, 16:34
shs666
Спасибо за решение проблемы с 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 форматом (который привел я или Вы в своем последнем посте). Чтобы намотать на ус и до конца врубиться в данную тему

Re: OpenLayers загрука векторов (маркеров из файла)
Добавлено: 09 май 2012, 17:40
Denis Rykov
Никаких сложностей, просто используете нужный формат и всё, пример обновил.