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...
-
2Here is one way not using html annotations nathanw.net/2016/02/04/live-svgsNathan W– Nathan W2016年02月20日 06:58:37 +00:00Commented Feb 20, 2016 at 6:58
-
that's exactly what I was searching for! Thanks @NathanWRiccardo– Riccardo2016年02月20日 08:32:57 +00:00Commented Feb 20, 2016 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– Riccardo2016年02月20日 13:43:16 +00:00Commented Feb 20, 2016 at 13:43
1 Answer 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...