Создать легенду карты, соответствующую OpenLayers.Style - PullRequest
6 голосов
/ 11 марта 2011

Я создал OpenLayers.Style, который окрашивает мои полигоны, стиль, который измеряет мои точки и весь этот джаз, теперь я хочу объяснить пользователю, что представляют эти стили.

Я не могуувидеть что-нибудь в OpenLayers, что позволяет мне рисовать свою легенду, используя эти стили.Кажется, все указывает на предполагаемый картографический сервер, который отправляет мне данные, которых у меня нет.

На данный момент мне кажется, что мне придется нарисовать несколько точек / областей выборки и взять их на экране, чтобы создать собственную легенду.Есть ли лучший способ сделать это, основываясь на стиле, чтобы мне не приходилось восстанавливать изображения при изменении стиля?

Обновление У меня был хороший ответ, чтоПолагается на GeoExt (и, следовательно, ExtJS), я все еще хотел бы услышать, есть ли у кого-нибудь ответ, совместимый с jQuery.Особенно, если это простой Javascript и OpenLayers.

Ответы [ 4 ]

3 голосов
/ 11 марта 2011

На самом деле OpenLayers не поддерживает то, что вы хотите (или, по крайней мере, я не знаю, как это сделать).Как сказал вам Чау, LegendPanel из GeoExt - ваша единственная надежда.

Интересные ссылки:

http://geoext.org/lib/GeoExt/widgets/LegendPanel.html

http://www.mail -archive.com / openlayers-users@lists.osgeo.org/msg01318.html

2 голосов
/ 12 мая 2017

Я смог решить свои легенды, используя класс ol.Map в качестве контейнера для символов. Может быть, немного хак, но, похоже, работает для большинства (?) Векторных слоев (у меня нет WMS).

Итак, что я делаю:

  1. переберите слои карты и выберите тип вектора с помощью

    if(lyr instanceof ol.layer.Vector)

  2. проверить, какой тип стиля используется и сохранить в массиве

    var style = lyr.getStyle();
    var image = style.getImage();
    if(image){
        if(image instanceof ol.style.Icon){
            //raster icon from url
            var icon2 = new ol.style.Icon( ({
                src: image.getSrc()
            }))
            var iconStyle2 = new ol.style.Style({
                image: icon2
            });
            row = {};
            row.style = iconStyle2;
            row.title = lyr.get('title');               
        }
        else{ //ol.style.RegularShape?
            row = {};
            row.style = style;
            row.title = lyr.get('title');               
        }
    }else{
        row = {};
        row.style = style;
        row.title = lyr.get('title');
    }
    
  3. также хранит тип геометрии

    //geometry type
    var feats = lyr.getSource().getFeatures();
    if (feats && feats.length>0){
        if(feats[0].getGeometry() instanceof ol.geom.Point || feats[0].getGeometry() instanceof ol.geom.MultiPoint){
            row.geomType="point";
        }else if (feats[0].getGeometry() instanceof ol.geom.LineString || feats[0].getGeometry() instanceof ol.geom.MultiLineString){
            row.geomType="line";
        }else{
            row.geomType="polygon";
        }
    }
    
  4. перебирает сохраненные строки легенды и создает необходимые элементы HTML, обычно это div для «мини-карты» и имя слоя

    for (i = 0; i < legendRows.length; i++) { 
        row = document.createElement("tr");
        //symbol
        cell = document.createElement("td");
        cell.style="width:35px";
        var div = document.createElement("div");
        div.style="width:32px; height:32px;";
        div.id = "mapLegendRowSymbolDiv" + i; 
        tble.appendChild(row);
        row.appendChild(cell);
        cell.appendChild(div);
        //layer title
        cell = document.createElement("td");      
        tble.appendChild(row);
        row.appendChild(cell);
        cell.innerHTML=legendRows[i].title; 
    }
    
    //append table
    $( "#legendText" ).empty();
    $( "#legendText" ).append(tble);
    
  5. как только HTML-элементы были добавлены на страницу, запустите карты и вставьте поддельные функции для отображения символов

    //loop legend rows and and insert the maps
    var extent = [0, 0, 32, 32];
    var projection = new ol.proj.Projection({
        code: 'xkcd-image',
        units: 'pixels',
        extent: extent
    });
    for (i = 0; i < legendRows.length; i++) { 
        //target div
        var targetDiv = document.getElementById("mapLegendRowSymbolDiv" + i);
        //layer for icon
        var sourceLegend = new ol.source.Vector({wrapX: false});
        var vectorLegend = new ol.layer.Vector({
            source: sourceLegend,
            style: legendRows[i].style
        });
        //map
        var mapLegend = new ol.Map({
            controls: [],
            layers: [
                new ol.layer.Image({
                    source: new ol.source.ImageStatic({
                        projection: projection,
                        imageExtent: extent
                    })
                }),
                vectorLegend
            ],
            target: targetDiv,
            view: new ol.View({
                projection: projection,
                center: ol.extent.getCenter(extent),
                zoom: 2,
                maxZoom: 2
            })
        });
        //icon feature depending on type
        var geom;
        if(legendRows[i].geomType=='point'){
            geom = new ol.geom.Point([16,16]);
        }else if(legendRows[i].geomType=='polygon'){
            var polyCoords = [];
            polyCoords.push([15.7, 15.7]);
            polyCoords.push([16.3, 15.7]);
            polyCoords.push([16.3, 16.3]);
            polyCoords.push([15.7, 16.3]);
            polyCoords.push([15.7, 15.7]);
            geom = new ol.geom.Polygon([polyCoords]);
        }else{
            var lineCoords = [];                
            lineCoords.push([15.6, 15.6]);
            lineCoords.push([16, 16]);
            lineCoords.push([16, 15.8]);
            lineCoords.push([16.4, 16.2]);
            geom = new ol.geom.LineString(lineCoords);
        }
        var feature = new ol.Feature({
            geometry: geom
        });
        vectorLegend.getSource().addFeature(feature);
    }   
    

Благодаря этому я смог создать и обновить отдельный диалог Legend (пользовательский интерфейс jQuery):

enter image description here

Я еще много не тестировал, могут быть некоторые проблемы с этим подходом ...

2 голосов
/ 18 января 2016

Как вариант, вы можете создавать SVG-элементы с такими же атрибутами, как в стиле OL3.Вот пример для стиля круга (вам понадобятся похожие методы и другие типы):

getIconLegend = function(style) {
    style = style.getImage();
    var radius = style.getRadius();
    var strokeWidth = style.getStroke().getWidth();
    var dx = radius + strokeWidth;

    var svgElem = $('<svg />')
        .attr({
            width: dx * 2,
            height: dx * 2
        });

    $('<circle />')
        .attr({
            cx: dx,
            cy: dx,
            r: radius,
            stroke: style.getStroke().getColor(),
            'stroke-width': strokeWidth,
            fill: style.getFill().getColor()
        })
        .appendTo(svgElem);

    // Convert DOM object to string to overcome from some SVG manipulation related oddities
    return $('<div>').append(svgElem).html();
}

Поскольку SVG-манипуляции с jQuery немного отличаются от HTML-элементов, я преобразовываю объект в строку в ответ.Подробности можно узнать из приложения jquery, не работающего с элементом svg?

Позже вы можете прикрепить значок легенды к HTML с помощью

$('#legendText').prepend($(getIconLegend(yourFeature.getStyle())));
0 голосов
/ 16 марта 2011

Самое простое, что вы можете получить, используя обычный OpenLayers, - это если вы используете сервис WMS вместо WFS или любой другой метод, который вы используете для получения функций. WMS имеет тип запроса GetLegendGraphic, который, как следует из названия, позволяет динамически извлекать изображение, показывающее, какой стиль применяется к слою.

...