1

I really like the html annotation tool in QGIS. My plan is to show a photo (web based image// jpg) on each point of my point shapefile. Unfortunately labels don't work as they do not parse HTML and the tooltips won't last for long (only on hoover, right?) and can't show external images like from a website. Images need to be local.

So is there a way to create a HTMLAnnotation using pyqgis? I mean, I can see the HTMLAnnotation block in the qgs file:

  <HtmlAnnotationItem hasFeature="0" feature="0" htmlfile="/home/ricckli/Desktop/test.html" vectorLayer="Accessibility20160219224444279">
<AnnotationItem frameHeight="360" canvasPosX="281" mapPosX="1514906.43412938853725791" canvasPosY="195" mapPositionFixed="1" mapPosY="6873695.00431403797119856" frameColorAlpha="255" frameBackgroundColorAlpha="255" frameBorderWidth="1" visible="1" offsetX="50" offsetY="-50" frameWidth="527" frameBackgroundColor="#ffffff" frameColor="#000000">
  <symbol alpha="1" clip_to_extent="1" type="marker" name="marker symbol">
    <layer pass="0" class="SimpleMarker" locked="0">
      <prop k="angle" v="0"/>
      <prop k="color" v="255,0,0,255"/>
      <prop k="horizontal_anchor_point" v="1"/>
      <prop k="name" v="circle"/>
      <prop k="offset" v="0,0"/>
      <prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
      <prop k="offset_unit" v="MM"/>
      <prop k="outline_color" v="0,0,0,255"/>
      <prop k="outline_style" v="solid"/>
      <prop k="outline_width" v="0"/>
      <prop k="outline_width_map_unit_scale" v="0,0,0,0,0,0"/>
      <prop k="outline_width_unit" v="MM"/>
      <prop k="scale_method" v="diameter"/>
      <prop k="size" v="2"/>
      <prop k="size_map_unit_scale" v="0,0,0,0,0,0"/>
      <prop k="size_unit" v="MM"/>
      <prop k="vertical_anchor_point" v="1"/>
    </layer>
  </symbol>
</AnnotationItem>

But I don't want to write it for my own for all the points. especially the canavasPosX and canvasPosy parameter...

  • 2
    Here is one way not using html annotations nathanw.net/2016/02/04/live-svgs – Nathan W Feb 20 '16 at 6:58
  • that's exactly what I was searching for! Thanks @NathanW – Riccardo Feb 20 '16 at 8:32
  • unfortunately this works for an enduser. I would love to embed it all in my plugin. My knowledge and my skillset is limited. So the main question is: how to do the script definition @NathanW mentioned in a programmatic way out of a plugin,.... – Riccardo Feb 20 '16 at 13:43
1

The current workaround is to style the data as "categorized" layer and create a single svg for every point:

layer = QgsVectorLayer('Point?crs=EPSG:4326', 'Flickr', "memory")
pr = layer.dataProvider()
pr.addAttributes([QgsField("thumbnail", QVariant.String)])
pr.addAttributes([QgsField("photoid", QVariant.String)])
layer.updateFields()
categories = []
renderer = QgsCategorizedSymbolRendererV2("photoid", categories)
layer.setRendererV2(renderer)
QgsMapLayerRegistry.instance().addMapLayer(layer)
for photo in json:
                fet = QgsFeature()
            #now read additional information:
                details = flickr.photos.getInfo(photo_id=photo['id'])
                thumb = 'https://farm' + str(photo['farm']) + '.staticflickr.com/' + str(photo['server']) + '/' + str(photo['id'])+ '_' + str(photo['secret'])+ '_t.jpg'
                photoid = str(photo['id'])
                fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(float(details['photo']['location']['longitude']),float(details['photo']['location']['latitude']))))
                geom = fet.geometry()
                fet.setAttributes([thumb,photoid])
                pr.addFeatures([fet])
                svg = """
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg>
  <g>
    <image xlink:href="data:image/jpeg;base64,{0}" height="256" width="320" />
  </g>
</svg>
"""
                data2 = requests.get(thumb, stream=True).content
                nameim = str(photo['id'])+'_t.jpg'
                b64response = base64.b64encode(data2)
                newsvg = svg.format(b64response).replace('\n','')
                path = tempfile.gettempdir() + os.sep + photo['id'] + '_t.jpg.svg'
                with open(path, 'w') as f:
                    f.write(newsvg)
                svgStyle = {}
                svgStyle['fill'] = '#0000ff'
                svgStyle['name'] = tempfile.gettempdir() + os.sep + photo['id'] + '_t.jpg.svg'
                svgStyle['outline'] = '#000000'
                svgStyle['size'] = '30'
                symLyr1 = QgsSvgMarkerSymbolLayerV2.create(svgStyle)
                sym = QgsSymbolV2.defaultSymbol(layer.geometryType())
                sym.changeSymbolLayer(0, symLyr1)
                category = QgsRendererCategoryV2(str(photo['id']), sym, str(photo['id']))
                categories.append(category)
                renderer = QgsCategorizedSymbolRendererV2("photoid", categories)
                layer.setRendererV2(renderer)
                layer.updateExtents()
                layer.triggerRepaint()

This is cartographic nonsense but otherwise I'll need to inject a python script into the QGIS style control of a layer...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.