Create a map legend to match OpenLayers.Style

I created OpenLayers.Style, which colors my polygons, a style that changes my glasses and all this jazz, now I want to explain to the user what these styles are.

I don't see anything in OpenLayers, which allows me to draw my own legend using these styles. Everything seems to point to a supposed map server that sends me data that I don’t have.

At the moment, it looks like I will need to draw some dots / areas and a screen to capture them in order to create my own legend. Is there a better way to do this based directly on the style, so I don’t need to restore images when the style changes?

Update I had a good answer that depends on GeoExt (and therefore ExtJS), I would still like to hear if anyone has a jQuery compatible answer. Especially if it's plain Javascript and OpenLayers.

+4
source share
4 answers

Actually, OpenLayers does not support what you want (or at least I don't know how to do this). As Chow told you, the GeoExt LegendPanel is your only hope.

Interesting links:

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

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

+3
source

Closest you can get what you want with simple OpenLayers if you use a WMS service instead of WFS or any other method that you use to extract functions. WMS has a GetLegendGraphic request type, which, as the name implies, allows you to dynamically retrieve an image showing which style is applied to the layer.

+1
source

As one option, you can create SVG elements with the same attributes as in OL3 style. Here is an example for a circle style (you will need similar methods and other types):

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(); } 

Since manipulating SVG with jQuery is slightly different from HTML elements, I convert the object to a string in response. Details can be found from the app jquery does not work with svg element

You can later insert the legend icon in HTML using

 $('#legendText').prepend($(getIconLegend(yourFeature.getStyle()))); 
+1
source

I managed to solve my legend requirements using the ol.Map class as a container for characters. Maybe a little hack, but it seems to work for most (?) Vector layers (I don't have WMS).

So what I do:

  • scroll through map layers and select vector type with

    if(lyr instanceof ol.layer.Vector)

  • check what type of style is used and store in an array

     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'); } 
  • also saves geometry type

     //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"; } } 
  • scroll through the currently saved legend lines and create the necessary HTML elements, usually a div for the minimap and the name of the layer

     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); 
  • after HTML elements have been added to the page, initiate maps and insert fake functions to display characters

     //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); } 

With this, I was able to create and update a separate Legend dialog box (jQuery UI):

enter image description here

I have not tested much yet, there may be some problems with this approach ...

0
source

Source: https://habr.com/ru/post/1343258/


All Articles