def getGroups(canvas, layers, restrictToExtent, extent, groupedLayers): group_list = [] no_group_list = [] usedGroups = [] currentVT = "" for count, layer in enumerate(layers): vts = layer.customProperty("VectorTilesReader/vector_tile_url") if (vts is not None): if (vts != currentVT): no_group_list.append("lyr_" + safeName(vts)) currentVT = vts else: try: if is25d(layer, canvas, restrictToExtent, extent): pass else: if layer.id() in groupedLayers: groupName = groupedLayers[layer.id()] if groupName not in usedGroups: group_list.append("group_" + safeName(groupName)) usedGroups.append(groupName) else: no_group_list.append("lyr_" + safeName(layer.name()) + "_" + unicode(count)) except: if layer.id() in groupedLayers: groupName = groupedLayers[layer.id()] if groupName not in usedGroups: group_list.append("group_" + safeName(groupName)) usedGroups.append(groupName) else: no_group_list.append("lyr_" + safeName(layer.name()) + "_" + unicode(count)) return (group_list, no_group_list, usedGroups)
def VTLayer(json_url): sln = safeName(json_url) key = json_url.split("?")[1] json = TileJSON(json_url) json.load() tile_url = json.tiles()[0].split("?")[0] key_url = "%s?%s" % (tile_url, key) styleSuffix = safeName(json_url) vtJS = """ var layer_%s = L.vectorGrid.protobuf("%s", { rendererFactory: L.svg.tile, //onEachFeature: label_%s, vectorTileLayerStyles: style_%s });""" % (sln, key_url, sln, styleSuffix) return vtJS
def build25d(canvas, layer, count): shadows = "" renderer = layer.renderer() renderContext = QgsRenderContext.fromMapSettings(canvas.mapSettings()) fields = layer.fields() renderer.startRender(renderContext, fields) for feat in layer.getFeatures(): if isinstance(renderer, QgsCategorizedSymbolRenderer): classAttribute = renderer.classAttribute() attrValue = feat.attribute(classAttribute) catIndex = renderer.categoryIndexForValue(attrValue) categories = renderer.categories() symbol = categories[catIndex].symbol() elif isinstance(renderer, QgsGraduatedSymbolRenderer): classAttribute = renderer.classAttribute() attrValue = feat.attribute(classAttribute) ranges = renderer.ranges() for range in ranges: if (attrValue >= range.lowerValue() and attrValue <= range.upperValue()): symbol = range.symbol().clone() else: symbol = renderer.symbolForFeature(feat, renderContext) symbolLayer = symbol.symbolLayer(0) if not symbolLayer.paintEffect().effectList()[0].enabled(): shadows = "'2015-07-15 10:00:00'" renderer.stopRender(renderContext) osmb = """ var osmb = new OSMBuildings(map).date(new Date({shadows})); osmb.set(json_{sln}_{count});""".format(shadows=shadows, sln=safeName(layer.name()), count=unicode(count)) return osmb
def layerToJavascript(iface, layer, encode2json, matchCRS, cluster, info, restrictToExtent, extent, count, vtLayers): (minResolution, maxResolution) = getScaleRes(layer) layerName = safeName(layer.name()) + "_" + unicode(count) layerAttr = getAttribution(layer) if layer.type() == layer.VectorLayer and not is25d(layer, iface.mapCanvas(), restrictToExtent, extent): renderer = layer.renderer() cluster = isCluster(cluster, renderer) hmRadius = 0 hmRamp = "" hmWeight = 0 hmWeightMax = 0 vts = layer.customProperty("VectorTilesReader/vector_tile_url") if vts is not None: if vts not in vtLayers: vtLayers.append(vts) return getVT(vts), vtLayers else: return "", vtLayers if isinstance(renderer, QgsHeatmapRenderer): (pointLayerType, hmRadius, hmRamp, hmWeight, hmWeightMax) = getHeatmap(layer, renderer) else: pointLayerType = "Vector" crsConvert = getCRS(iface, matchCRS) if layer.providerType() == "WFS" and not encode2json: return getWFS(layer, layerName, layerAttr, cluster, minResolution, maxResolution), vtLayers else: return getJSON(layerName, crsConvert, layerAttr, cluster, pointLayerType, minResolution, maxResolution, hmRadius, hmRamp, hmWeight, hmWeightMax, renderer, layer), vtLayers elif layer.type() == layer.RasterLayer: if layer.providerType().lower() == "wms": source = layer.source() opacity = layer.renderer().opacity() d = parse_qs(source) if "type" in d and d["type"][0] == "xyz": return getXYZ(layerName, opacity, minResolution, maxResolution, layerAttr, d["url"][0]), vtLayers elif "tileMatrixSet" in d: return getWMTS(layer, d, layerAttr, layerName, opacity, minResolution, maxResolution), vtLayers else: return getWMS(source, layer, layerAttr, layerName, opacity, minResolution, maxResolution, info), vtLayers elif layer.providerType().lower() == "gdal": return getRaster(iface, layer, layerName, layerAttr, minResolution, maxResolution, matchCRS), vtLayers
def buildGroups(groups, qms, layer_names_id): groupVars = "" groupedLayers = {} for group, groupLayers in groups.items(): groupLayerObjs = "" for layer in groupLayers: vts = layer.customProperty("VectorTilesReader/vector_tile_url") if qms: if isinstance(layer, TileLayer): continue if vts is not None: continue groupLayerObjs += ("lyr_" + safeName(layer.name()) + "_" + layer_names_id[layer.id()] + ",") groupVars += ('''var %s = new ol.layer.Group({ layers: [%s], title: "%s"});\n''' % ("group_" + safeName(group), groupLayerObjs, group)) for layer in groupLayers: groupedLayers[layer.id()] = safeName(group) return (groupVars, groupedLayers)
def writeScriptIncludes(layers, json, matchCRS): geojsonVars = "" wfsVars = "" styleVars = "" for count, (layer, encode2json) in enumerate(zip(layers, json)): vts = layer.customProperty("VectorTilesReader/vector_tile_url") sln = safeName(layer.name()) + "_" + unicode(count) if layer.type() == layer.VectorLayer: if layer.providerType() != "WFS" or encode2json: if vts is None: geojsonVars += ('<script src="layers/%s"></script>' % (sln + ".js")) else: layerSource = layer.source() if ("retrictToRequestBBOX" in layerSource or "restrictToRequestBBOX" in layerSource): provider = layer.dataProvider() uri = QgsDataSourceUri(provider.dataSourceUri()) wfsURL = uri.param("url") wfsTypename = uri.param("typename") wfsSRS = uri.param("srsname") layerSource = wfsURL layerSource += "?SERVICE=WFS&VERSION=1.0.0&" layerSource += "REQUEST=GetFeature&TYPENAME=" layerSource += wfsTypename layerSource += "&SRSNAME=" layerSource += wfsSRS if not matchCRS: layerSource = re.sub(r'SRSNAME\=EPSG\:\d+', 'SRSNAME=EPSG:3857', layerSource) layerSource += "&outputFormat=text%2Fjavascript&" layerSource += "format_options=callback%3A" layerSource += "get" + sln + "Json" wfsVars += ('<script src="%s"></script>' % layerSource) if vts is not None: sln = safeName(vts) styleVars += ('<script src="styles/%s_style.js">' '</script>' % sln) return (geojsonVars, wfsVars, styleVars)
def layersAnd25d(layers, canvas, restrictToExtent, extent, qms): mapLayers = [] layerObjs = [] osmb = "" for count, layer in enumerate(layers): if is25d(layer, canvas, restrictToExtent, extent): osmb = build25d(canvas, layer, count) else: if (qms and not isinstance(layer, TileLayer)) or not qms: mapLayers.append("lyr_" + safeName(layer.name()) + "_" + unicode(count)) layerObjs.append(layer) return (mapLayers, layerObjs, osmb)
def getVTLabels(vtLabels): labels = [] for k, v in vtLabels.items(): labels.append(""" function label_%s(feature, featureLayer, vtLayer, tileCoords) { var context = { feature: feature, variables: {} }; %s }""" % (safeName(k), v)) labelString = "".join(labels) return labelString
def getVisibility(mapLayers, layers, visible): visibility = "" currentVT = "" for layer, layerObj, v in zip(mapLayers, layers, visible): vts = layerObj.customProperty("VectorTilesReader/vector_tile_url") if vts is None or vts != currentVT: if vts is not None: lname = "lyr_%s" % safeName(vts) else: lname = layer visibility += "\n".join(["%s.setVisible(%s);" % ( lname, unicode(v).lower())]) if vts is not None: currentVT = vts return visibility
def addLayersList(basemapList, matchCRS, layer_list, cluster, legends, collapsed): if len(basemapList) < 2 or matchCRS: controlStart = """ var baseMaps = {};""" else: comma = "" controlStart = """ var baseMaps = {""" for count, basemap in enumerate(basemapList): controlStart += comma + "'" + unicode(basemap) controlStart += "': basemap" + unicode(count) comma = ", " controlStart += "};" controlStart += """ L.control.layers(baseMaps,{""" layersList = controlStart lyrCount = len(layer_list) - 1 for i, clustered in zip(reversed(layer_list), reversed(cluster)): try: rawLayerName = i.name() safeLayerName = safeName(rawLayerName) + "_" + unicode(lyrCount) lyrCount -= 1 if i.type() == QgsMapLayer.VectorLayer: testDump = i.renderer().dump() if (clustered and i.geometryType() == QgsWkbTypes.PointGeometry): new_layer = "'" + legends[safeLayerName].replace("'", "\'") new_layer += "': cluster_" "" + safeLayerName + "," else: new_layer = "'" + legends[safeLayerName].replace("'", "\'") new_layer += "': layer_" + safeLayerName + "," layersList += new_layer elif i.type() == QgsMapLayer.RasterLayer: new_layer = '"' + rawLayerName.replace("'", "\'") + '"' new_layer += ": layer_" + safeLayerName + """,""" layersList += new_layer except: QgsMessageLog.logMessage(traceback.format_exc(), "qgis2web", level=Qgis.Critical) controlEnd = "}" if collapsed: controlEnd += ",{collapsed:false}" controlEnd += ").addTo(map);" layersList += controlEnd return layersList
def addLayersList(basemapList, matchCRS, layer_list, cluster, legends, collapsed): if len(basemapList) < 2 or matchCRS: controlStart = """ var baseMaps = {};""" else: comma = "" controlStart = """ var baseMaps = {""" for count, basemap in enumerate(basemapList): controlStart += comma + "'" + unicode(basemap) controlStart += "': basemap" + unicode(count) comma = ", " controlStart += "};" controlStart += """ L.control.layers(baseMaps,{""" layersList = controlStart lyrCount = len(layer_list) - 1 for i, clustered in zip(reversed(layer_list), reversed(cluster)): try: rawLayerName = i.name() safeLayerName = safeName(rawLayerName) + "_" + unicode(lyrCount) lyrCount -= 1 if i.type() == QgsMapLayer.VectorLayer: testDump = i.renderer().dump() if (clustered and i.geometryType() == QgsWkbTypes.PointGeometry): new_layer = "'" + legends[safeLayerName].replace("'", "\'") new_layer += "': cluster_""" + safeLayerName + "," else: new_layer = "'" + legends[safeLayerName].replace("'", "\'") new_layer += "': layer_" + safeLayerName + "," layersList += new_layer elif i.type() == QgsMapLayer.RasterLayer: new_layer = '"' + rawLayerName.replace("'", "\'") + '"' new_layer += ": overlay_" + safeLayerName + """,""" layersList += new_layer except: QgsMessageLog.logMessage(traceback.format_exc(), "qgis2web", level=Qgis.Critical) controlEnd = "}" if collapsed: controlEnd += ",{collapsed:false}" controlEnd += ").addTo(map);" layersList += controlEnd return layersList
def getVTStyles(vtStyles): vtStyleString = "" for (vts, lyrs) in vtStyles.items(): vtStyleString += """ style_%s = {""" % safeName(vts) for (lyr, styles) in lyrs.items(): vtStyleString += """ %s: [""" % lyr for style in styles: if style == "": style = "{}" vtStyleString += "%s," % style vtStyleString += "]," vtStyleString = vtStyleString.replace(",]", "]") vtStyleString += "}" return vtStyleString
def addLayersList(basemapList, matchCRS, layer_list, cluster, legends, collapsed): layerName_list = [] for ct, layer in enumerate(layer_list): sln = "'lyr_%s_%d_0', '%s'" % (safeName( layer.name()), ct, layer.name()) layerName_list.insert(0, sln) layersList = """ var toggleableLayerIds = [%s]; for (var i = 0; i < toggleableLayerIds.length; i=i+2) { var id = toggleableLayerIds[i]; var layerName = toggleableLayerIds[i+1] var link = document.createElement('a'); link.href = '#'; link.className = 'active'; link.layer = id; link.textContent = layerName; link.onclick = function (e) { var clickedLayer = this.layer; e.preventDefault(); e.stopPropagation(); var visibility = map.getLayoutProperty(clickedLayer, 'visibility'); if (typeof visibility === 'undefined' || visibility == 'visible') { map.setLayoutProperty(clickedLayer, 'visibility', 'none'); this.className = ''; } else { this.className = 'active'; map.setLayoutProperty(clickedLayer, 'visibility', 'visible'); } }; var layers = document.getElementById('menu'); layers.appendChild(link); }""" % (",".join(layerName_list)) return layersList
def getVT(json_url): sln = safeName(json_url) key = json_url.split("?")[1] json = TileJSON(json_url) json.load() tile_url = json.tiles()[0].split("?")[0] key_url = "%s?%s" % (tile_url, key) layerCode = """ var lyr_%s = new ol.layer.VectorTile({ source: new ol.source.VectorTile({ format: new ol.format.MVT(), url: '%s', tileGrid: new ol.tilegrid.createXYZ({ tileSize: 512, maxZoom: 14 }), tilePixelRatio: 8 }), style: style_%s }); """ % (sln, key_url, sln) return layerCode
def getVT(json_url): sln = safeName(json_url) try: key = json_url.split("?")[1] except: key = "" json = TileJSON(json_url) json.load() tile_url = json.tiles()[0].split("?")[0] key_url = "%s?%s" % (tile_url, key) layerCode = """ var lyr_%s = new ol.layer.VectorTile({ source: new ol.source.VectorTile({ format: new ol.format.MVT(), url: '%s', tileGrid: new ol.tilegrid.createXYZ({ tileSize: 512, maxZoom: 14 }), tilePixelRatio: 8 }), style: style_%s }); """ % (sln, key_url, sln) return layerCode
def writeVectorLayer(layer, safeLayerName, usedFields, highlight, popupsOnHover, popup, outputProjectFileName, wfsLayers, cluster, visible, json, legends, new_src, canvas, zIndex, restrictToExtent, extent, feedback, labelCode, vtLabels, vtStyles, useMultiStyle, useHeat, useVT, useShapes, useOSMB): vts = layer.customProperty("VectorTilesReader/vector_tile_url") feedback.showFeedback("Writing %s as JSON..." % layer.name()) zIndex = zIndex + 400 markerFolder = os.path.join(outputProjectFileName, "markers") labeltext, vtLabels = getLabels(layer, safeLayerName, outputProjectFileName, vts, vtLabels) labelCode += labeltext (new_pop, popFuncs) = getPopups(layer, safeLayerName, highlight, popupsOnHover, popup, vts) renderer = layer.renderer() layer_transp = 1 - (float(layer.opacity()) / 100) style = "" useMapUnits = False if is25d(layer, canvas, restrictToExtent, extent): useOSMB = True shadows = "" renderer = layer.renderer() renderContext = QgsRenderContext.fromMapSettings(canvas.mapSettings()) fields = layer.fields() renderer.startRender(renderContext, fields) for feat in layer.getFeatures(): if isinstance(renderer, QgsCategorizedSymbolRenderer): classAttribute = renderer.classAttribute() attrValue = feat.attribute(classAttribute) catIndex = renderer.categoryIndexForValue(attrValue) categories = renderer.categories() symbol = categories[catIndex].symbol() elif isinstance(renderer, QgsGraduatedSymbolRenderer): classAttribute = renderer.classAttribute() attrValue = feat.attribute(classAttribute) ranges = renderer.ranges() for range in ranges: if (attrValue >= range.lowerValue() and attrValue <= range.upperValue()): symbol = range.symbol().clone() else: symbol = renderer.symbolForFeature(feat, renderContext) symbolLayer = symbol.symbolLayer(0) if not symbolLayer.paintEffect().effectList()[0].enabled(): shadows = "'2015-07-15 10:00:00'" renderer.stopRender(renderContext) new_obj = """ var osmb = new OSMBuildings(map).date(new Date({shadows})); osmb.set(json_{sln});""".format(shadows=shadows, sln=safeLayerName) elif isinstance(renderer, QgsHeatmapRenderer): useHeat = True new_obj = heatmapLayer(layer, safeLayerName, renderer) elif vts is not None: useVT = True if vts in vtStyles: new_obj = "" addVT = False else: new_obj = VTLayer(vts) vtStyles[vts] = {} addVT = True vtStyle = vtStyles[vts] (style, markerType, useMapUnits, useShapes) = getLayerStyle(layer, safeLayerName, markerFolder, outputProjectFileName, useShapes) style = style.replace("feature.properties['", "feature.['") if layer.name() not in vtStyle: vtStyle[layer.name()] = ["", "", ""] isLayer = False geom = TYPE_MAP[layer.wkbType()].replace("Multi", "") if geom == "Point": index = 0 isLayer = True if geom == "LineString": index = 1 isLayer = True if geom == "Polygon": index = 2 isLayer = True if isLayer: vtStyles[vts][layer.name()][index] = style style = "" else: (style, markerType, useMapUnits, useShapes) = getLayerStyle(layer, safeLayerName, markerFolder, outputProjectFileName, useShapes) (legend, symbol) = getLegend(layer, renderer, outputProjectFileName, safeLayerName) legends[safeLayerName] = legend (new_obj, legends, wfsLayers, useMultiStyle) = getLayer(layer, renderer, safeLayerName, outputProjectFileName, usedFields, legends, cluster, json, wfsLayers, markerType, useMultiStyle, symbol) blend = BLEND_MODES[layer.blendMode()] if vts is None: new_obj = u"""{style} map.createPane('pane_{sln}'); map.getPane('pane_{sln}').style.zIndex = {zIndex}; map.getPane('pane_{sln}').style['mix-blend-mode'] = '{blend}'; {new_obj}""".format(style=style, sln=safeLayerName, zIndex=zIndex, blend=blend, new_obj=new_obj) if usedFields != 0: new_src += new_pop new_src += """ """ + new_obj if is25d(layer, canvas, restrictToExtent, extent): pass elif vts is not None: if addVT: sln = safeName(vts) new_src += """ map.addLayer(layer_""" + sln + """);""" else: new_src += """ bounds_group.addLayer(layer_""" + safeLayerName + """);""" if visible: if cluster is False: new_src += """ map.addLayer(layer_""" + safeLayerName + """);""" else: new_src += """ cluster_""" + safeLayerName + """.addTo(map);""" feedback.completeStep() return (new_src, legends, wfsLayers, labelCode, vtLabels, vtStyles, useMapUnits, useMultiStyle, useHeat, useVT, useShapes, useOSMB)
def exportStyles(layers, folder, clustered): stylesFolder = os.path.join(folder, "styles") QDir().mkpath(stylesFolder) legendFolder = os.path.join(stylesFolder, "legend") QDir().mkpath(legendFolder) vtStyles = {} mapUnitLayers = [] for count, (layer, cluster) in enumerate(zip(layers, clustered)): sln = safeName(layer.name()) + "_" + unicode(count) if layer.type() != layer.VectorLayer: continue pattern = "" setPattern = "" vts = layer.customProperty("VectorTilesReader/vector_tile_source") labelText = getLabels(layer, folder, sln) defs = "var size = 0;\nvar placement = 'point';" try: renderer = layer.renderer() layer_alpha = layer.opacity() if isinstance(renderer, QgsSingleSymbolRenderer): (style, pattern, setPattern, value, useMapUnits) = singleSymbol(renderer, stylesFolder, layer_alpha, sln, legendFolder, layer) elif isinstance(renderer, QgsCategorizedSymbolRenderer): (style, pattern, setPattern, value, defs, useMapUnits) = categorized(defs, sln, layer, renderer, legendFolder, stylesFolder, layer_alpha) elif isinstance(renderer, QgsGraduatedSymbolRenderer): (style, pattern, setPattern, value, useMapUnits) = graduated(layer, renderer, legendFolder, sln, stylesFolder, layer_alpha) elif isinstance(renderer, QgsRuleBasedRenderer): (style, pattern, setPattern, value, useMapUnits) = ruleBased(renderer, folder, stylesFolder, layer_alpha, sln, layer) else: style = """ var style = [ new ol.style.Style({ text: createTextStyle(feature, resolution, labelText, labelFont, labelFill, placement) })];""" useMapUnits = False if useMapUnits: if vts is None: mapUnitLayers.append(sln) else: mapUnitLayers.append(safeName(vts)) (labelRes, size, face, color) = getLabelFormat(layer) if style != "": geom = TYPE_MAP[layer.wkbType()].replace("Multi", "") style = getStyle(style, cluster, labelRes, labelText, sln, size, face, color, value, geom) else: style = "''" except Exception as e: style = "" QgsApplication.messageLog().logMessage(traceback.format_exc(), "qgis2web", level=Qgis.Critical) if vts is None: path = os.path.join(stylesFolder, sln + "_style.js") with codecs.open(path, "w", "utf-8") as f: f.write( '''%(defs)s %(pattern)s var style_%(name)s = %(style)s; %(setPattern)s''' % { "defs": defs, "pattern": pattern, "name": sln, "style": style, "setPattern": setPattern }) elif style != "" and style != "''": new_vtStyle = "if (feature.get('layer') == " new_vtStyle += """'%s' && feature.getGeometry().getType() == '%s'){ return %s(feature, resolution); }""" % (layer.name(), TYPE_MAP[layer.wkbType()].replace("Multi", ""), style) try: old_vtStyles = vtStyles[vts] new_vtStyles = """%s %s""" % (old_vtStyles, new_vtStyle) except: new_vtStyles = new_vtStyle vtStyles[vts] = new_vtStyles for k, v in vtStyles.items(): styleName = safeName(k) styleString = v path = os.path.join(stylesFolder, styleName + "_style.js") with codecs.open(path, "w", "utf-8") as f: f.write( ''' var style_%(name)s = function(feature, resolution) { %(style)s; }''' % { "defs": defs, "pattern": pattern, "name": styleName, "style": styleString, "setPattern": setPattern }) return mapUnitLayers
def writeLeaflet(cls, iface, feedback, folder, layer_list, visible, interactive, cluster, json, getFeatureInfo, params, popup): outputProjectFileName = folder QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) legends = {} mapUnitLayers = [] canvas = iface.mapCanvas() project = QgsProject.instance() mapSettings = canvas.mapSettings() title = project.title() pluginDir = os.path.dirname(os.path.realpath(__file__)) stamp = datetime.now().strftime("%Y_%m_%d-%H_%M_%S_%f") outputProjectFileName = os.path.join(outputProjectFileName, 'qgis2web_' + stamp) outputIndex = os.path.join(outputProjectFileName, 'index.html') minify = params["Data export"]["Minify GeoJSON files"] precision = params["Data export"]["Precision"] extent = params["Scale/Zoom"]["Extent"] minZoom = params["Scale/Zoom"]["Min zoom level"] maxZoom = params["Scale/Zoom"]["Max zoom level"] restrictToExtent = params["Scale/Zoom"]["Restrict to extent"] matchCRS = params["Appearance"]["Match project CRS"] addressSearch = params["Appearance"]["Add address search"] locate = params["Appearance"]["Geolocate user"] measure = params["Appearance"]["Measure tool"] highlight = params["Appearance"]["Highlight on hover"] layerSearch = params["Appearance"]["Layer search"] popupsOnHover = params["Appearance"]["Show popups on hover"] template = params["Appearance"]["Template"] widgetAccent = params["Appearance"]["Widget Icon"] widgetBackground = params["Appearance"]["Widget Background"] usedFields = [ALL_ATTRIBUTES] * len(popup) QgsApplication.initQgis() dataStore, cssStore = writeFoldersAndFiles(pluginDir, feedback, outputProjectFileName, cluster, measure, matchCRS, layerSearch, canvas, addressSearch, locate) writeCSS(cssStore, mapSettings.backgroundColor().name(), feedback, widgetAccent, widgetBackground) wfsLayers = "" labelCode = "" vtLabels = {} vtStyles = {} useMultiStyle = False useHeat = False useVT = False useShapes = False useOSMB = False useWMS = False useWMTS = False useRaster = False scaleDependentLayers = "" labelVisibility = "" new_src = "" jsons = "" crs = QgsCoordinateReferenceSystem.EpsgCrsId exp_crs = QgsCoordinateReferenceSystem(4326, crs) lyrCount = 0 for layer, jsonEncode, eachPopup, clst in zip(layer_list, json, popup, cluster): rawLayerName = layer.name() safeLayerName = safeName(rawLayerName) + "_" + str(lyrCount) vts = layer.customProperty("VectorTilesReader/vector_tile_url") if layer.providerType() != 'WFS' or jsonEncode is True: if layer.type() == QgsMapLayer.VectorLayer and vts is None: feedback.showFeedback('Exporting %s to JSON...' % layer.name()) exportVector(layer, safeLayerName, dataStore, restrictToExtent, iface, extent, precision, exp_crs, minify) jsons += jsonScript(safeLayerName) scaleDependentLabels = \ scaleDependentLabelScript(layer, safeLayerName) labelVisibility += scaleDependentLabels feedback.completeStep() elif layer.type() == QgsMapLayer.RasterLayer: if layer.dataProvider().name() != "wms": layersFolder = os.path.join(outputProjectFileName, "data") exportRaster(layer, lyrCount, layersFolder, feedback, iface, matchCRS) if layer.hasScaleBasedVisibility(): scaleDependentLayers += scaleDependentLayerScript( layer, safeLayerName, clst) lyrCount += 1 if scaleDependentLayers != "": scaleDependentLayers = scaleDependentScript(scaleDependentLayers) crsSrc = mapSettings.destinationCrs() crsAuthId = crsSrc.authid() crsProj4 = crsSrc.toProj4() middle = """ """ if highlight or popupsOnHover: selectionColor = mapSettings.selectionColor().name() middle += highlightScript(highlight, popupsOnHover, selectionColor) if extent == "Canvas extent": pt0 = canvas.extent() crsDest = QgsCoordinateReferenceSystem(4326) try: xform = QgsCoordinateTransform(crsSrc, crsDest, QgsProject.instance()) except Exception: xform = QgsCoordinateTransform(crsSrc, crsDest) pt1 = xform.transformBoundingBox(pt0) bounds = '[[' + str(pt1.yMinimum()) + ',' bounds += str(pt1.xMinimum()) + '],[' bounds += str(pt1.yMaximum()) + ',' bounds += str(pt1.xMaximum()) + ']]' if matchCRS and crsAuthId != 'EPSG:4326': middle += crsScript(crsAuthId, crsProj4) else: bounds = 0 if matchCRS and crsAuthId != 'EPSG:4326': middle += crsScript(crsAuthId, crsProj4) middle += mapScript(extent, matchCRS, crsAuthId, measure, maxZoom, minZoom, bounds, locate) middle += featureGroupsScript() extentCode = extentScript(extent, restrictToExtent) new_src += middle new_src += extentCode for count, layer in enumerate(layer_list): rawLayerName = layer.name() safeLayerName = safeName(rawLayerName) + "_" + str(count) if (layer.type() == QgsMapLayer.VectorLayer and layer.wkbType() != QgsWkbTypes.NoGeometry): (new_src, legends, wfsLayers, labelCode, vtLabels, vtStyles, useMapUnits, useMultiStyle, useHeat, useVT, useShapes, useOSMB) = writeVectorLayer( layer, safeLayerName, usedFields[count], highlight, popupsOnHover, popup[count], outputProjectFileName, wfsLayers, cluster[count], visible[count], interactive[count], json[count], legends, new_src, canvas, count, restrictToExtent, extent, feedback, labelCode, vtLabels, vtStyles, useMultiStyle, useHeat, useVT, useShapes, useOSMB) if useMapUnits: mapUnitLayers.append(safeLayerName) elif layer.type() == QgsMapLayer.RasterLayer: if layer.dataProvider().name() == "wms": feedback.showFeedback('Writing %s as WMS layer...' % layer.name()) new_obj, useWMS, useWMTS = wmsScript( layer, safeLayerName, useWMS, useWMTS, getFeatureInfo[count]) feedback.completeStep() else: useRaster = True feedback.showFeedback('Writing %s as raster layer...' % layer.name()) new_obj = rasterScript(layer, safeLayerName) feedback.completeStep() if visible[count]: new_obj += """ map.addLayer(layer_""" + safeLayerName + """);""" new_src += new_obj the_src = new_src new_src = jsons + """ <script>""" if len(mapUnitLayers) > 0: new_src += """ var m2px = 1; function newM2px() { var centerLatLng = map.getCenter(); var pointC = map.latLngToContainerPoint(centerLatLng); var pointX = [pointC.x + 100, pointC.y]; var latLngC = map.containerPointToLatLng(pointC); var latLngX = map.containerPointToLatLng(pointX); var distanceX = latLngC.distanceTo(latLngX)/100; reciprocal = 1 / distanceX; m2px = reciprocal; } function geoStyle(m) { return Math.ceil(m * m2px); }""" new_src += getVTStyles(vtStyles) new_src += getVTLabels(vtLabels) new_src += the_src + scaleDependentLayers if title != "": titleStart = titleSubScript(title) new_src += titleStart if addressSearch: address_text = addressSearchScript() new_src += address_text if (params["Appearance"]["Add layers list"] and params["Appearance"]["Add layers list"] != "" and params["Appearance"]["Add layers list"] != "None"): new_src += addLayersList( [], matchCRS, layer_list, cluster, legends, params["Appearance"]["Add layers list"] == "Expanded") if project.readBoolEntry("ScaleBar", "/Enabled", False)[0]: # placement = project.readNumEntry("ScaleBar", "/Placement", 0)[0] # placement = PLACEMENT[placement] # end = scaleBar(placement) end = scaleBar() else: end = '' layerType = "layer" try: if cluster[count]: layerType = "cluster" except Exception: pass searchLayer = "%s_%s" % (layerType, params["Appearance"]["Search layer"]) labelList = [] for count, layer in enumerate(layer_list): vts = layer.customProperty("VectorTilesReader/vector_tile_url") safeLayerName = safeName(layer.name()) + "_" + str(count) if (layer.type() == QgsMapLayer.VectorLayer and vts is None): labelling = layer.labeling() if labelling is not None: palyr = labelling.settings() if palyr.fieldName and palyr.fieldName != "": labelList.append("layer_%s" % safeLayerName) labelsList = ",".join(labelList) end += endHTMLscript(wfsLayers, layerSearch, labelCode, labelVisibility, searchLayer, useHeat, useRaster, labelsList, mapUnitLayers) new_src += end try: writeHTMLstart(outputIndex, title, cluster, addressSearch, measure, matchCRS, layerSearch, canvas, locate, new_src, template, feedback, useMultiStyle, useHeat, useShapes, useOSMB, useWMS, useWMTS, useVT) except Exception: QgsMessageLog.logMessage(traceback.format_exc(), "qgis2web", level=Qgis.Critical) finally: QApplication.restoreOverrideCursor() return outputIndex
def writeLayersAndGroups(layers, groups, visible, folder, popup, settings, json, matchCRS, clustered, getFeatureInfo, iface, restrictToExtent, extent, bounds, authid): canvas = iface.mapCanvas() layerVars = "" layer_names_id = {} vtLayers = [] for count, (layer, encode2json, cluster, info) in enumerate(zip(layers, json, clustered, getFeatureInfo)): layer_names_id[layer.id()] = str(count) if is25d(layer, canvas, restrictToExtent, extent): pass else: (layerVar, vtLayers) = layerToJavascript(iface, layer, encode2json, matchCRS, cluster, info, restrictToExtent, extent, count, vtLayers) layerVars += "\n".join([layerVar]) (groupVars, groupedLayers) = buildGroups(groups, qms, layer_names_id) (mapLayers, layerObjs, osmb) = layersAnd25d(layers, canvas, restrictToExtent, extent, qms) visibility = getVisibility(mapLayers, layerObjs, visible) usedGroups = [] (group_list, no_group_list, usedGroups) = getGroups(canvas, layers, restrictToExtent, extent, groupedLayers) layersList = [] currentVT = "" for layer in (group_list + no_group_list): layersList.append(layer) layersListString = "var layersList = [" + ",".join(layersList) + "];" fieldAliases = "" fieldImages = "" fieldLabels = "" blend_mode = "" for count, (layer, labels) in enumerate(zip(layers, popup)): vts = layer.customProperty("VectorTilesReader/vector_tile_url") sln = safeName(layer.name()) + "_" + unicode(count) if (layer.type() == layer.VectorLayer and vts is None and not isinstance(layer.renderer(), QgsHeatmapRenderer) and not is25d(layer, canvas, restrictToExtent, extent)): (fieldLabels, fieldAliases, fieldImages, blend_mode) = getPopups(layer, labels, sln, fieldLabels, fieldAliases, fieldImages) path = os.path.join(folder, "layers", "layers.js") with codecs.open(path, "w", "utf-8") as f: if matchCRS: f.write("""ol.proj.get("%s").setExtent(%s); """ % (authid, bounds)) f.write("""var wms_layers = [];\n""") f.write(layerVars + "\n") f.write(groupVars + "\n") f.write(visibility + "\n") f.write(layersListString + "\n") f.write(fieldAliases) f.write(fieldImages) f.write(fieldLabels) f.write(blend_mode) return osmb
def writeMapbox(cls, iface, feedback, folder, layer_list, visible, cluster, json, getFeatureInfo, params, popup): outputProjectFileName = folder QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) legends = {} mapUnitLayers = [] canvas = iface.mapCanvas() project = QgsProject.instance() mapSettings = canvas.mapSettings() title = project.title() pluginDir = os.path.dirname(os.path.realpath(__file__)) stamp = datetime.now().strftime("%Y_%m_%d-%H_%M_%S_%f") outputProjectFileName = os.path.join(outputProjectFileName, 'qgis2web_' + unicode(stamp)) outputIndex = os.path.join(outputProjectFileName, 'index.html') minify = params["Data export"]["Minify GeoJSON files"] precision = params["Data export"]["Precision"] extent = params["Scale/Zoom"]["Extent"] minZoom = params["Scale/Zoom"]["Min zoom level"] maxZoom = params["Scale/Zoom"]["Max zoom level"] restrictToExtent = params["Scale/Zoom"]["Restrict to extent"] matchCRS = params["Appearance"]["Match project CRS"] addressSearch = params["Appearance"]["Add address search"] locate = params["Appearance"]["Geolocate user"] measure = params["Appearance"]["Measure tool"] highlight = params["Appearance"]["Highlight on hover"] layerSearch = params["Appearance"]["Layer search"] popupsOnHover = params["Appearance"]["Show popups on hover"] template = params["Appearance"]["Template"] widgetAccent = params["Appearance"]["Widget Icon"] widgetBackground = params["Appearance"]["Widget Background"] usedFields = [ALL_ATTRIBUTES] * len(popup) QgsApplication.initQgis() crsSrc = mapSettings.destinationCrs() crs = QgsCoordinateReferenceSystem.EpsgCrsId crsDest = QgsCoordinateReferenceSystem(4326, crs) xform = QgsCoordinateTransform(crsSrc, crsDest, project) dataStore, cssStore = writeFoldersAndFiles(pluginDir, feedback, outputProjectFileName, cluster, measure, matchCRS, layerSearch, canvas, addressSearch, locate) writeCSS(cssStore, mapSettings.backgroundColor().name(), feedback, widgetAccent, widgetBackground) wfsLayers = "" labelCode = "" vtLabels = {} vtStyles = {} useMultiStyle = False useHeat = False useVT = False useShapes = False useOSMB = False useWMS = False useWMTS = False useRaster = False vtSources = [] layers = [ """ { "id": "background", "type": "background", "layout": {}, "paint": { "background-color": "%s" } }""" % mapSettings.backgroundColor().name() ] scaleDependentLayers = "" labelVisibility = "" new_src = "" jsons = "" sources = [] crs = QgsCoordinateReferenceSystem.EpsgCrsId exp_crs = QgsCoordinateReferenceSystem(4326, crs) lyrCount = 0 for layer, jsonEncode, eachPopup, clst in zip(layer_list, json, popup, cluster): rawLayerName = layer.name() safeLayerName = safeName(rawLayerName) + "_" + unicode(lyrCount) vts = layer.customProperty("VectorTilesReader/vector_tile_url") if layer.providerType() != 'WFS' or jsonEncode is True: if layer.type() == QgsMapLayer.VectorLayer and vts is None: feedback.showFeedback('Exporting %s to JSON...' % layer.name()) exportVector(layer, safeLayerName, dataStore, restrictToExtent, iface, extent, precision, exp_crs, minify) jsons += jsonScript(safeLayerName) sources.append(""" "%s": { "type": "geojson", "data": json_%s } """ % (safeLayerName, safeLayerName)) scaleDependentLabels = \ scaleDependentLabelScript(layer, safeLayerName) labelVisibility += scaleDependentLabels feedback.completeStep() elif layer.type() == QgsMapLayer.RasterLayer: if layer.dataProvider().name() != "wms": layersFolder = os.path.join(outputProjectFileName, "data") exportRaster(layer, lyrCount, layersFolder, feedback, iface, matchCRS) rasterPath = './data/' + safeLayerName + '.png' extent = layer.extent() bbox = xform.transformBoundingBox(extent) sources.append(""" "%s": { "type": "image", "url": "%s", "coordinates": [ [%f, %f], [%f, %f], [%f, %f], [%f, %f] ] }""" % (safeLayerName, rasterPath, bbox.xMinimum(), bbox.yMinimum(), bbox.xMaximum(), bbox.yMinimum(), bbox.xMaximum(), bbox.yMaximum(), bbox.xMinimum(), bbox.yMaximum())) else: tileProps = parse_qs(layer.source()) if ('type' in tileProps and tileProps['type'][0] == "xyz"): sources.append(""" "%s": { "type": "raster", "tiles": ["%s"], "tileSize": 256 }""" % (safeLayerName, tileProps['url'][0])) else: url = "%s&%s" % (tileProps['url'][0], layer.source()) sources.append(""" "%s": { "type": "raster", "tiles": ["%s"], "tileSize": 256 }""" % (safeLayerName, url)) lyrCount += 1 popupCode = "" for count, layer in enumerate(layer_list): rawLayerName = layer.name() safeLayerName = safeName(rawLayerName) + "_" + unicode(count) if layer.type() == QgsMapLayer.VectorLayer: (new_src, legends, wfsLayers, labelCode, vtLabels, vtStyles, useMapUnits, useMultiStyle, useHeat, useVT, useShapes, useOSMB, vtSources, layers, popups) = writeVectorLayer( layer, safeLayerName, usedFields[count], highlight, popupsOnHover, popup[count], outputProjectFileName, wfsLayers, cluster[count], visible[count], json[count], legends, new_src, canvas, count, restrictToExtent, extent, feedback, labelCode, vtLabels, vtStyles, useMultiStyle, useHeat, useVT, useShapes, useOSMB, vtSources, layers) popupCode += popups elif layer.type() == QgsMapLayer.RasterLayer: if layer.dataProvider().name() == "wms": feedback.showFeedback('Writing %s as WMS layer...' % layer.name()) layers.append(wmsScript(layer, safeLayerName)) feedback.completeStep() else: feedback.showFeedback('Writing %s as raster layer...' % layer.name()) layers.append(rasterScript(layer, safeLayerName)) feedback.completeStep() glyphs = ("https://glfonts.lukasmartinelli.ch/fonts/{fontstack}/" "{range}.pbf") s = """ var styleJSON = { "version": 8, "name": "qgis2web export", "pitch": 0, "light": { "intensity": 0.2 }, "sources": {%s}, "sprite": "", "glyphs": "%s", "layers": [%s], }""" % (",".join(vtSources + sources), glyphs, ",".join(layers)) mbStore = os.path.join(outputProjectFileName, 'mapbox') if not os.path.exists(mbStore): shutil.copytree(os.path.join(os.path.dirname(__file__), "mapbox"), mbStore) with codecs.open(os.path.join(mbStore, "style.js"), 'w', encoding='utf-8') as f: f.write(unicode(s)) f.close() pt0 = canvas.center() pt1 = xform.transform(pt0) center = '[' + str(pt1.x()) + ',' center += str(pt1.y()) + ']' center.replace('nan', '0') bearing = 360 - canvas.rotation() zoom = scaleToZoom(canvas.scale()) attribution = ('<a href=' '"https://github.com/tomchadwin/qgis2web" ' 'target="_blank">qgis2web</a> · ' '<a href="https://github.com/mapbox/mapbox-gl-js" ' 'target="_blank">Mapbox GL JS</a> · ' '<a href="https://qgis.org" target="_blank">QGIS</a>') new_src = jsons + """ <script src="./mapbox/style.js"></script> <script src="./js/Autolinker.min.js"></script> <script> var map = new mapboxgl.Map({ container: 'map', style: styleJSON, center: %s, zoom: %s, bearing: %s, attributionControl: false }); map.addControl(new mapboxgl.NavigationControl()); map.addControl(new mapboxgl.AttributionControl({ customAttribution: '%s', compact: false })); %s </script>""" % (center, zoom, bearing, attribution, popupCode) # try: writeHTMLstart(outputIndex, title, cluster, addressSearch, measure, matchCRS, layerSearch, canvas, locate, new_src, template, feedback, useMultiStyle, useHeat, useShapes, useOSMB, useWMS, useWMTS, useVT) # except Exception as e: # QgsMessageLog.logMessage(traceback.format_exc(), "qgis2web", # level=QgsMessageLog.CRITICAL) # QApplication.restoreOverrideCursor() # finally: # QApplication.restoreOverrideCursor() return outputIndex
def exportStyles(layers, folder, clustered): stylesFolder = os.path.join(folder, "styles") QDir().mkpath(stylesFolder) legendFolder = os.path.join(stylesFolder, "legend") QDir().mkpath(legendFolder) vtStyles = {} mapUnitLayers = [] for count, (layer, cluster) in enumerate(zip(layers, clustered)): sln = safeName(layer.name()) + "_" + unicode(count) if layer.type() != layer.VectorLayer: continue pattern = "" setPattern = "" vts = layer.customProperty("VectorTilesReader/vector_tile_url") labelText = getLabels(layer, folder, sln) defs = "var size = 0;\nvar placement = 'point';" try: renderer = layer.renderer() layer_alpha = layer.opacity() if isinstance(renderer, QgsSingleSymbolRenderer): (style, pattern, setPattern, value, useMapUnits) = singleSymbol(renderer, stylesFolder, layer_alpha, sln, legendFolder, layer) elif isinstance(renderer, QgsCategorizedSymbolRenderer): (style, pattern, setPattern, value, defs, useMapUnits) = categorized(defs, sln, layer, renderer, legendFolder, stylesFolder, layer_alpha) elif isinstance(renderer, QgsGraduatedSymbolRenderer): (style, pattern, setPattern, value, useMapUnits) = graduated(layer, renderer, legendFolder, sln, stylesFolder, layer_alpha) elif isinstance(renderer, QgsRuleBasedRenderer): (style, pattern, setPattern, value, useMapUnits) = ruleBased(renderer, folder, stylesFolder, layer_alpha, sln, layer) else: style = """ var style = [ new ol.style.Style({ text: createTextStyle(feature, resolution, labelText, labelFont, labelFill, placement) })];""" useMapUnits = False if useMapUnits: if vts is None: mapUnitLayers.append(sln) else: mapUnitLayers.append(safeName(vts)) (labelRes, size, face, color) = getLabelFormat(layer) if style != "": geom = TYPE_MAP[layer.wkbType()].replace("Multi", "") style = getStyle(style, cluster, labelRes, labelText, sln, size, face, color, value, geom) else: style = "''" except Exception as e: style = "" QgsApplication.messageLog().logMessage(traceback.format_exc(), "qgis2web", level=Qgis.Critical) if vts is None: path = os.path.join(stylesFolder, sln + "_style.js") with codecs.open(path, "w", "utf-8") as f: f.write('''%(defs)s %(pattern)s var style_%(name)s = %(style)s; %(setPattern)s''' % {"defs": defs, "pattern": pattern, "name": sln, "style": style, "setPattern": setPattern}) elif style != "" and style != "''": new_vtStyle = "if (feature.get('layer') == " new_vtStyle += """'%s' && feature.getGeometry().getType() == '%s'){ return %s(feature, resolution); }""" % ( layer.name(), TYPE_MAP[layer.wkbType()].replace("Multi", ""), style) try: old_vtStyles = vtStyles[vts] new_vtStyles = """%s %s""" % (old_vtStyles, new_vtStyle) except: new_vtStyles = new_vtStyle vtStyles[vts] = new_vtStyles for k, v in vtStyles.items(): styleName = safeName(k) styleString = v path = os.path.join(stylesFolder, styleName + "_style.js") with codecs.open(path, "w", "utf-8") as f: f.write(''' var style_%(name)s = function(feature, resolution) { %(style)s; }''' % {"defs": defs, "pattern": pattern, "name": styleName, "style": styleString, "setPattern": setPattern}) return mapUnitLayers
def writeLeaflet( cls, iface, feedback, folder, layer_list, visible, cluster, json, getFeatureInfo, params, popup): outputProjectFileName = folder QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) legends = {} mapUnitLayers = [] canvas = iface.mapCanvas() project = QgsProject.instance() mapSettings = canvas.mapSettings() title = project.title() pluginDir = os.path.dirname(os.path.realpath(__file__)) stamp = datetime.now().strftime("%Y_%m_%d-%H_%M_%S_%f") outputProjectFileName = os.path.join(outputProjectFileName, 'qgis2web_' + unicode(stamp)) outputIndex = os.path.join(outputProjectFileName, 'index.html') minify = params["Data export"]["Minify GeoJSON files"] precision = params["Data export"]["Precision"] extent = params["Scale/Zoom"]["Extent"] minZoom = params["Scale/Zoom"]["Min zoom level"] maxZoom = params["Scale/Zoom"]["Max zoom level"] restrictToExtent = params["Scale/Zoom"]["Restrict to extent"] matchCRS = params["Appearance"]["Match project CRS"] addressSearch = params["Appearance"]["Add address search"] locate = params["Appearance"]["Geolocate user"] measure = params["Appearance"]["Measure tool"] highlight = params["Appearance"]["Highlight on hover"] layerSearch = params["Appearance"]["Layer search"] popupsOnHover = params["Appearance"]["Show popups on hover"] template = params["Appearance"]["Template"] widgetAccent = params["Appearance"]["Widget Icon"] widgetBackground = params["Appearance"]["Widget Background"] usedFields = [ALL_ATTRIBUTES] * len(popup) QgsApplication.initQgis() dataStore, cssStore = writeFoldersAndFiles(pluginDir, feedback, outputProjectFileName, cluster, measure, matchCRS, layerSearch, canvas, addressSearch, locate) writeCSS(cssStore, mapSettings.backgroundColor().name(), feedback, widgetAccent, widgetBackground) wfsLayers = "" labelCode = "" vtLabels = {} vtStyles = {} useMultiStyle = False useHeat = False useVT = False useShapes = False useOSMB = False useWMS = False useWMTS = False useRaster = False scaleDependentLayers = "" labelVisibility = "" new_src = "" jsons = "" crs = QgsCoordinateReferenceSystem.EpsgCrsId exp_crs = QgsCoordinateReferenceSystem(4326, crs) lyrCount = 0 for layer, jsonEncode, eachPopup, clst in zip(layer_list, json, popup, cluster): rawLayerName = layer.name() safeLayerName = safeName(rawLayerName) + "_" + unicode(lyrCount) vts = layer.customProperty("VectorTilesReader/vector_tile_url") if layer.providerType() != 'WFS' or jsonEncode is True: if layer.type() == QgsMapLayer.VectorLayer and vts is None: feedback.showFeedback('Exporting %s to JSON...' % layer.name()) exportVector(layer, safeLayerName, dataStore, restrictToExtent, iface, extent, precision, exp_crs, minify) jsons += jsonScript(safeLayerName) scaleDependentLabels = \ scaleDependentLabelScript(layer, safeLayerName) labelVisibility += scaleDependentLabels feedback.completeStep() elif layer.type() == QgsMapLayer.RasterLayer: if layer.dataProvider().name() != "wms": layersFolder = os.path.join(outputProjectFileName, "data") exportRaster(layer, lyrCount, layersFolder, feedback, iface, matchCRS) if layer.hasScaleBasedVisibility(): scaleDependentLayers += scaleDependentLayerScript( layer, safeLayerName, clst) lyrCount += 1 if scaleDependentLayers != "": scaleDependentLayers = scaleDependentScript(scaleDependentLayers) crsSrc = mapSettings.destinationCrs() crsAuthId = crsSrc.authid() crsProj4 = crsSrc.toProj4() middle = """ """ if highlight or popupsOnHover: selectionColor = mapSettings.selectionColor().name() middle += highlightScript(highlight, popupsOnHover, selectionColor) if extent == "Canvas extent": pt0 = canvas.extent() crsDest = QgsCoordinateReferenceSystem(4326) try: xform = QgsCoordinateTransform(crsSrc, crsDest, QgsProject.instance()) except: xform = QgsCoordinateTransform(crsSrc, crsDest) pt1 = xform.transformBoundingBox(pt0) bbox_canvas = [pt1.yMinimum(), pt1.yMaximum(), pt1.xMinimum(), pt1.xMaximum()] bounds = '[[' + unicode(pt1.yMinimum()) + ',' bounds += unicode(pt1.xMinimum()) + '],[' bounds += unicode(pt1.yMaximum()) + ',' bounds += unicode(pt1.xMaximum()) + ']]' if matchCRS and crsAuthId != 'EPSG:4326': middle += crsScript(crsAuthId, crsProj4) else: bounds = 0 if matchCRS and crsAuthId != 'EPSG:4326': middle += crsScript(crsAuthId, crsProj4) middle += mapScript(extent, matchCRS, crsAuthId, measure, maxZoom, minZoom, bounds, locate) middle += featureGroupsScript() extentCode = extentScript(extent, restrictToExtent) new_src += middle new_src += extentCode for count, layer in enumerate(layer_list): rawLayerName = layer.name() safeLayerName = safeName(rawLayerName) + "_" + unicode(count) if layer.type() == QgsMapLayer.VectorLayer: (new_src, legends, wfsLayers, labelCode, vtLabels, vtStyles, useMapUnits, useMultiStyle, useHeat, useVT, useShapes, useOSMB) = writeVectorLayer(layer, safeLayerName, usedFields[count], highlight, popupsOnHover, popup[count], outputProjectFileName, wfsLayers, cluster[count], visible[count], json[count], legends, new_src, canvas, count, restrictToExtent, extent, feedback, labelCode, vtLabels, vtStyles, useMultiStyle, useHeat, useVT, useShapes, useOSMB) if useMapUnits: mapUnitLayers.append(safeLayerName) elif layer.type() == QgsMapLayer.RasterLayer: if layer.dataProvider().name() == "wms": feedback.showFeedback('Writing %s as WMS layer...' % layer.name()) new_obj, useWMS, useWMTS = wmsScript(layer, safeLayerName, useWMS, useWMTS, getFeatureInfo[count]) feedback.completeStep() else: useRaster = True feedback.showFeedback('Writing %s as raster layer...' % layer.name()) new_obj = rasterScript(layer, safeLayerName) feedback.completeStep() if visible[count]: new_obj += """ map.addLayer(overlay_""" + safeLayerName + """);""" new_src += new_obj the_src = new_src new_src = jsons + """ <script>""" if len(mapUnitLayers) > 0: new_src += """ var m2px = 1; function newM2px() { var centerLatLng = map.getCenter(); var pointC = map.latLngToContainerPoint(centerLatLng); var pointX = [pointC.x + 100, pointC.y]; var latLngC = map.containerPointToLatLng(pointC); var latLngX = map.containerPointToLatLng(pointX); var distanceX = latLngC.distanceTo(latLngX)/100; reciprocal = 1 / distanceX; m2px = reciprocal; } function geoStyle(m) { return Math.ceil(m * m2px); }""" new_src += getVTStyles(vtStyles) new_src += getVTLabels(vtLabels) new_src += the_src + scaleDependentLayers if title != "": titleStart = unicode(titleSubScript(title)) new_src += unicode(titleStart) if addressSearch: address_text = addressSearchScript() new_src += address_text if (params["Appearance"]["Add layers list"] and params["Appearance"]["Add layers list"] != "" and params["Appearance"]["Add layers list"] != "None"): new_src += addLayersList( [], matchCRS, layer_list, cluster, legends, params["Appearance"]["Add layers list"] == "Expanded") if project.readBoolEntry("ScaleBar", "/Enabled", False)[0]: # placement = project.readNumEntry("ScaleBar", "/Placement", 0)[0] # placement = PLACEMENT[placement] # end = scaleBar(placement) end = scaleBar() else: end = '' layerType = "layer" try: if cluster[count]: layerType = "cluster" except: pass searchLayer = "%s_%s" % (layerType, params["Appearance"]["Search layer"]) labelList = [] for count, layer in enumerate(layer_list): vts = layer.customProperty("VectorTilesReader/vector_tile_url") safeLayerName = re.sub(r'[\W_]+', '', layer.name()) + "_" + unicode(count) if (layer.type() == QgsMapLayer.VectorLayer and vts is None): labelling = layer.labeling() if labelling is not None: palyr = labelling.settings() if palyr.fieldName and palyr.fieldName != "": labelList.append("layer_%s" % safeLayerName) labelsList = ",".join(labelList) end += endHTMLscript(wfsLayers, layerSearch, labelCode, labelVisibility, searchLayer, useHeat, useRaster, labelsList, mapUnitLayers) new_src += end try: writeHTMLstart(outputIndex, title, cluster, addressSearch, measure, matchCRS, layerSearch, canvas, locate, new_src, template, feedback, useMultiStyle, useHeat, useShapes, useOSMB, useWMS, useWMTS, useVT) except Exception as e: QgsMessageLog.logMessage(traceback.format_exc(), "qgis2web", level=QgsMessageLog.CRITICAL) QApplication.restoreOverrideCursor() finally: QApplication.restoreOverrideCursor() return outputIndex
def endHTMLscript(wfsLayers, layerSearch, filterItems, labelCode, labels, searchLayer, useHeat, useRaster, labelsList, mapUnitLayers): if labels == "": endHTML = "" else: endHTML = """ map.on("zoomend", function(){ %s });""" % labels if wfsLayers == "": endHTML += """ setBounds(); %s""" % labelCode endHTML += labels if len(mapUnitLayers) > 0: lyrs = [] for layer in mapUnitLayers: lyrs.append(""" layer_%s.setStyle(style_%s_0);""" % (layer, layer)) lyrScripts = "".join(lyrs) endHTML += """ newM2px(); %s map.on("zoomend", function(){ newM2px(); %s });""" % (lyrScripts, lyrScripts) if layerSearch != "None": searchVals = layerSearch.split(": ") endHTML += """ map.addControl(new L.Control.Search({{ layer: {searchLayer}, initial: false, hideMarkerOnCollapse: true, propertyName: '{field}'}})); document.getElementsByClassName('search-button')[0].className += ' fa fa-binoculars'; """.format(searchLayer=searchLayer, field=searchVals[1]) filterItems = sorted(filterItems, key=lambda k: k['type']) filterNum = len(filterItems) if filterNum != 0: endHTML += """ var mapDiv = document.getElementById('map'); var row = document.createElement('div'); row.className="row"; row.id="all"; row.style.height = "100%"; var col1 = document.createElement('div'); col1.className="col9"; col1.id = "mapWindow"; col1.style.height = "99%"; col1.style.width = "80%"; col1.style.display = "inline-block"; var col2 = document.createElement('div'); col2.className="col3"; col2.id = "menu"; col2.style.display = "inline-block"; mapDiv.parentNode.insertBefore(row, mapDiv); document.getElementById("all").appendChild(col1); document.getElementById("all").appendChild(col2); col1.appendChild(mapDiv) var Filters = {""" filterList = [] for item in range(0, filterNum): filterList.append('"' + filterItems[item]["name"] + '": "' + filterItems[item]["type"] + '"') endHTML += ",".join(filterList) + "};" endHTML += """ function filterFunc() { map.eachLayer(function(lyr){ if ("options" in lyr && "dataVar" in lyr["options"]){ features = this[lyr["options"]["dataVar"]].features.slice(0); try{ for (key in Filters){ if (Filters[key] == "str" || Filters[key] == "bool"){ var selection = []; var options = document.getElementById("sel_" + key).options for (var i=0; i < options.length; i++) { if (options[i].selected) selection.push(options[i].value); } try{ if (key in features[0].properties){ for (i = features.length - 1; i >= 0; --i){ if (selection.indexOf( features[i].properties[key])<0 && selection.length>0) { features.splice(i,1); } } } } catch(err){ } } if (Filters[key] == "int"){ sliderVals = document.getElementById( "div_" + key).noUiSlider.get(); try{ if (key in features[0].properties){ for (i = features.length - 1; i >= 0; --i){ if (parseInt(features[i].properties[key]) < sliderVals[0] || parseInt(features[i].properties[key]) > sliderVals[1]){ features.splice(i,1); } } } } catch(err){ } } if (Filters[key] == "real"){ sliderVals = document.getElementById( "div_" + key).noUiSlider.get(); try{ if (key in features[0].properties){ for (i = features.length - 1; i >= 0; --i){ if (features[i].properties[key] < sliderVals[0] || features[i].properties[key] > sliderVals[1]){ features.splice(i,1); } } } } catch(err){ } } if (Filters[key] == "date" || Filters[key] == "datetime" || Filters[key] == "time"){ try{ if (key in features[0].properties){ HTMLkey = key.replace(/[&\/\\#,+()$~%.'":*?<>{} ]/g, ''); startdate = document.getElementById("dat_" + HTMLkey + "_date1").value.replace(" ", "T"); enddate = document.getElementById("dat_" + HTMLkey + "_date2").value.replace(" ", "T"); for (i = features.length - 1; i >= 0; --i){ if (features[i].properties[key] < startdate || features[i].properties[key] > enddate){ features.splice(i,1); } } } } catch(err){ } } } } catch(err){ } this[lyr["options"]["layerName"]].clearLayers(); this[lyr["options"]["layerName"]].addData(features); } }) }""" for item in range(0, filterNum): itemName = filterItems[item]["name"] if filterItems[item]["type"] in ["str", "bool"]: selSize = 2 if filterItems[item]["type"] == "str": if len(filterItems[item]["values"]) > 10: selSize = 10 else: selSize = len(filterItems[item]["values"]) endHTML += """ document.getElementById("menu").appendChild( document.createElement("div")); var div_{nameS} = document.createElement('div'); div_{nameS}.id = "div_{name}"; div_{nameS}.className= "filterselect"; document.getElementById("menu").appendChild(div_{nameS}); sel_{nameS} = document.createElement('select'); sel_{nameS}.multiple = true; sel_{nameS}.size = {s}; sel_{nameS}.id = "sel_{name}"; var {nameS}_options_str = "<option value='' unselected></option>"; sel_{nameS}.onchange = function(){{filterFunc()}}; """.format(name=itemName, nameS=safeName(itemName), s=selSize) for entry in filterItems[item]["values"]: endHTML += """ {nameS}_options_str += '<option value="{e}">{e}</option>'; """.format(e=entry, name=itemName, nameS=safeName(itemName)) endHTML += """ sel_{nameS}.innerHTML = {nameS}_options_str; div_{nameS}.appendChild(sel_{nameS}); var lab_{nameS} = document.createElement('div'); lab_{nameS}.innerHTML = '{name}'; lab_{nameS}.className = 'filterLabel'; div_{nameS}.appendChild(lab_{nameS}); """.format(name=itemName, nameS=safeName(itemName)) if filterItems[item]["type"] in ["int", "real"]: endHTML += """ document.getElementById("menu").appendChild( document.createElement("div")); var div_{nameS} = document.createElement("div"); div_{nameS}.id = "div_{name}"; div_{nameS}.className = "slider"; document.getElementById("menu").appendChild(div_{nameS}); var lab_{nameS} = document.createElement('p'); lab_{nameS}.innerHTML = '{name}: <span id="val_{name}"></span>'; lab_{nameS}.className = 'slider'; document.getElementById("menu").appendChild(lab_{nameS}); var sel_{nameS} = document.getElementById('div_{name}'); """.format(name=itemName, nameS=safeName(itemName)) if filterItems[item]["type"] == "int": endHTML += """ noUiSlider.create(sel_{nameS}, {{ connect: true, start: [{min}, {max}], step: 1, format: wNumb({{ decimals: 0, }}), range: {{ min: {min}, max: {max} }} }}); sel_{nameS}.noUiSlider.on('update', function (values) {{ filterVals =[]; for (value in values){{ filterVals.push(parseInt(value)) }} val_{nameS} = document.getElementById('val_{name}'); val_{nameS}.innerHTML = values.join(' - '); filterFunc() }});""".format(name=itemName, nameS=safeName(itemName), min=filterItems[item]["values"][0], max=filterItems[item]["values"][1]) else: endHTML += """ noUiSlider.create(sel_{nameS}, {{ connect: true, start: [{min}, {max}], range: {{ min: {min}, max: {max} }} }}); sel_{nameS}.noUiSlider.on('update', function (values) {{ val_{nameS} = document.getElementById('val_{name}'); val_{nameS}.innerHTML = values.join(' - '); filterFunc() }}); """.format(name=itemName, nameS=safeName(itemName), min=filterItems[item]["values"][0], max=filterItems[item]["values"][1]) if filterItems[item]["type"] in ["date", "time", "datetime"]: startDate = filterItems[item]["values"][0] endDate = filterItems[item]["values"][1] d = "'YYYY-mm-dd'" t = "'HH:ii:ss'" Y1 = startDate.toString("yyyy") M1 = startDate.toString("M") D1 = startDate.toString("d") hh1 = startDate.toString("h") mm1 = startDate.toString("m") ss1 = startDate.toString("s") Y2 = endDate.toString("yyyy") M2 = endDate.toString("M") D2 = endDate.toString("d") hh2 = endDate.toString("h") mm2 = endDate.toString("m") ss2 = endDate.toString("s") if filterItems[item]["type"] == "date": t = "false" hh1 = 0 mm1 = 0 ss1 = 0 hh2 = 0 mm2 = 0 ss2 = 0 ds = startDate.toMSecsSinceEpoch() de = endDate.toMSecsSinceEpoch() if filterItems[item]["type"] == "datetime": ds = startDate.toMSecsSinceEpoch() de = endDate.toMSecsSinceEpoch() if filterItems[item]["type"] == "time": d = "false" Y1 = 0 M1 = 1 D1 = 0 Y2 = 0 M2 = 1 D2 = 0 ds = "null" de = "null" endHTML += """ document.getElementById("menu").appendChild( document.createElement("div")); var div_{nameS}_date1 = document.createElement("div"); div_{nameS}_date1.id = "div_{nameS}_date1"; div_{nameS}_date1.className= "filterselect"; document.getElementById("menu").appendChild(div_{nameS}_date1); dat_{nameS}_date1 = document.createElement('input'); dat_{nameS}_date1.type = "text"; dat_{nameS}_date1.id = "dat_{nameS}_date1"; div_{nameS}_date1.appendChild(dat_{nameS}_date1); var lab_{nameS}_date1 = document.createElement('p'); lab_{nameS}_date1.innerHTML = '{name} from'; document.getElementById("div_{nameS}_date1").appendChild( lab_{nameS}_date1); document.addEventListener("DOMContentLoaded", function(){{ tail.DateTime("#dat_{nameS}_date1", {{ dateStart: {ds}, dateEnd: {de}, dateFormat: {d}, timeFormat: {t}, today: false, weekStart: 1, position: "left", closeButton: true, stayOpen: true, timeStepMinutes:1, timeStepSeconds: 1 }}).selectDate({Y1},{M1}-1,{D1},{hh1},{mm1},{ss1}); tail.DateTime("#dat_{nameS}_date1").reload() """.format(name=itemName, nameS=safeName(itemName), de=de, ds=ds, d=d, t=t, Y1=Y1, M1=M1, D1=D1, hh1=hh1, mm1=mm1, ss1=ss1) endHTML += """ tail.DateTime("#dat_{nameS}_date2", {{ dateStart: {ds}, dateEnd: {de}, dateFormat: {d}, timeFormat: {t}, today: false, weekStart: 1, position: "left", closeButton: true, stayOpen: true, timeStepMinutes:1, timeStepSeconds: 1 }}).selectDate({Y2},{M2}-1,{D2},{hh2},{mm2},{ss2}); tail.DateTime("#dat_{nameS}_date2").reload() filterFunc() dat_{nameS}_date1.onchange = function(){{filterFunc()}}; dat_{nameS}_date2.onchange = function(){{filterFunc()}}; }}); """.format(name=itemName, nameS=safeName(itemName), de=de, ds=ds, d=d, t=t, Y2=Y2, M2=M2, D2=D2, hh2=hh2, mm2=mm2, ss2=ss2) endHTML += """ var div_{nameS}_date2 = document.createElement("div"); div_{nameS}_date2.id = "div_{nameS}_date2"; div_{nameS}_date2.className= "filterselect"; document.getElementById("menu").appendChild(div_{nameS}_date2); dat_{nameS}_date2 = document.createElement('input'); dat_{nameS}_date2.type = "text"; dat_{nameS}_date2.id = "dat_{nameS}_date2"; div_{nameS}_date2.appendChild(dat_{nameS}_date2); var lab_{nameS}_date2 = document.createElement('p'); lab_{nameS}_date2.innerHTML = '{name} till'; document.getElementById("div_{nameS}_date2") .appendChild(lab_{nameS}_date2); """.format(name=itemName, nameS=safeName(itemName)) if useHeat: endHTML += """ function geoJson2heat(geojson, weight) { return geojson.features.map(function(feature) { return [ feature.geometry.coordinates[1], feature.geometry.coordinates[0], feature.properties[weight] ]; }); }""" if useRaster: endHTML += """ L.ImageOverlay.include({ getBounds: function () { return this._bounds; } });""" if labelsList != "": endHTML += """ resetLabels([%s]); map.on("zoomend", function(){ resetLabels([%s]); }); map.on("layeradd", function(){ resetLabels([%s]); }); map.on("layerremove", function(){ resetLabels([%s]); });""" % (labelsList, labelsList, labelsList, labelsList) endHTML += """ </script>%s""" % wfsLayers return endHTML
def addLayersList(basemapList, matchCRS, layer_list, groups, cluster, legends, collapsed): groupedLayers = {} for group, groupLayers in groups.items(): groupLayerObjs = "" groupList = [] groupedLayers[group] = groupList layerName_list = [] layer_abstracts = {} layer_legends = {} for ct, layer in enumerate(layer_list): layer_id = ("lyr_%s_%d_0") % (safeName(layer.name()), ct) found = False legendHTML = ("<div class=\"menu-legend\">" + legends[safeName(layer.name()) + "_" + str(ct)] + "</div>") layer_abstracts[layer_id] = layer.metadata().abstract() layer_legends[layer_id] = legendHTML for group, groupLayers in groups.items(): for layer2 in groupLayers: if layer == layer2: sln2 = layer.name() groupedLayers[group].insert(0, sln2) groupedLayers[group].insert(0, layer_id) QgsMessageLog.logMessage("layer found in group: " + layer.name()) found = True break if found == True: break if found == True: continue legendHTML = ("<div class=\"menu-legend\">" + legends[safeName(layer.name()) + "_" + str(ct)] + "</div>") sln = ("'%s', '%s'") % (layer_id, layer.name()) layerName_list.insert(0, sln) layersList = """ map.on('load', function(){ var toggleableLayerIds = [%s]; var toggleableGroups = %s; var layerLegends = %s; var layerAbstracts = %s; function ShowInfoClick(e){ e.preventDefault(); e.stopPropagation(); var id = $(this).attr("layerId"); var name = $(this).attr("layerName"); if(!($('#modal-details-content').length == 0)) { $('#modal-details-content').empty(); $('#modal-details-text').empty(); $('#modal-details-holder').css("maxWidth","800px"); $('#modal-details-content').html("<h3>"+name+"</h3><div>" + layerAbstracts[id].replace(/\\n/g, "<br />") + '</div><div class="pt-5"><h6>Legenda</h6>' +layerLegends[id]+ "</div>"); $("#modal-details").modal('show'); } else { console.log("Trying to show info of layer, but modal does not exist."); } } function ToggleLayer(e){ var clickedLayer = this.layer; e.preventDefault(); e.stopPropagation(); var visibility = map.getLayoutProperty(clickedLayer, 'visibility'); if (typeof visibility === 'undefined' || visibility == 'visible') { map.setLayoutProperty(clickedLayer, 'visibility', 'none'); this.className = ''; } else { this.className = 'active'; map.setLayoutProperty(clickedLayer, 'visibility', 'visible'); } } function CreateLink(id,layerName){ var hasAbstract = false; if(layerAbstracts[id]) hasAbstract = true; var link2 = document.createElement('a'); link2.href = '#'; var visibility = map.getLayoutProperty(id, 'visibility'); if(visibility == 'visible') link2.className = 'active'; link2.layer = id; if(hasAbstract) link2.innerHTML = "<p>" + layerName + '<i class="fas fa-info-circle"></i></p>' + layerLegends[id]; else link2.innerHTML = "<p>" + layerName + "</p>" + layerLegends[id]; link2.onclick = ToggleLayer; if(hasAbstract){ var infoLink = $(link2).find('i'); infoLink.attr("layerId",id); infoLink.attr("layerName",layerName); infoLink.click(ShowInfoClick); } return link2; } var layers = document.getElementById('menu'); for (var i = 0; i < toggleableLayerIds.length; i=i+2) { var id = toggleableLayerIds[i]; var layerName = toggleableLayerIds[i+1] var link = CreateLink(id,layerName); layers.appendChild(link); } for (var groupName in toggleableGroups) { console.log(groupName); let link = document.createElement('a'); link.href = '#'; var visibility = map.getLayoutProperty(toggleableGroups[groupName][0], 'visibility'); if(visibility == 'visible') link.className = 'active'; link.innerHTML = "<p>" + groupName + "</p>"; // Group click link.onclick = function (e) { e.preventDefault(); e.stopPropagation(); if(this.className == "active"){ this.className = ""; for(var j = 0; j < link.children.length; j++){ link2 = link.children[j]; map.setLayoutProperty(link2.layer, 'visibility', 'none'); } } else{ this.className = "active"; for(var j = 0; j < link.children.length; j++){ link2 = link.children[j]; if(link2.className == "active"){ map.setLayoutProperty(link2.layer, 'visibility', 'visible'); } } } }; var layers = document.getElementById('menu'); layers.appendChild(link); //actual layer in group for (var i = 0; i < toggleableGroups[groupName].length; i=i+2) { var id = toggleableGroups[groupName][i]; var layerName = toggleableGroups[groupName][i+1] var link2 = CreateLink(id,layerName); link.appendChild(link2); } } });""" % (",".join(layerName_list), json.dumps(groupedLayers), json.dumps(layer_legends), json.dumps(layer_abstracts)) return layersList