qgis / QGIS-Enhancement-Proposals

QEP's (QGIS Enhancement Proposals) are used in the process of creating and discussing new enhancements for QGIS

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Dynamic SVG

3nids opened this issue · comments

QGIS Enhancement: Dynamic SVG

Date 2020/10/10

Author Denis Rouzaud (@3nids)

Contact denis@opengis.ch

maintainer @3nids

Version QGIS 3.x

Summary

There is a common need to customize SVG images from the data.
For quite some time (about 10 years), QGIS supports the customization of fill color, stroke color and stroke width (https://blog.sourcepole.ch/2011/06/30/svg-symbols-in-qgis-with-modifiable-colors/).

We propose to extend this to allow the customization of any part of the SVGs.

This opens the door to having an unlimited number of editable colors, to draw custom paths, and even write data-defined texts.
For road signs, this means that the direction text could be dynamically written using a layer attribute.

image

Current SVG situation and issue

The current approach to customize the fill color, stroke color and stroke width is based on a proposal for SVG 2.0 dating from 2009 which actually was never integrated.
https://www.w3.org/TR/2009/WD-SVGParamPrimer-20090616/

This means that our approach is based on something unofficial.

Main drawback of this approach is that the SVG is not correctly rendered in an SVG editor, and the SVG parameters might be altered when saved.

The original proposal from 2009 has been adapted and is proposed for SVG 2.1
w3c/svgwg#128
https://tabatkins.github.io/specs/svg-params/

New approach sounds more powerful, but it is not backward compatible. It is a bit more obtrusive in the SVG code and more complex to write. Until this is officially accepted, it does not sound reasonable to integrate it in our code base.

Proposed approach

We propose to reuse the same approach, and dynamically replace any param(name) in the SVG code.

UX

A new table would be added to the SVG configuration to enter parameters as pairs of name (str) and expressions (str).

SVG Cache

QgsSvgCache::svgAsImage, cacheEntry, findExistingEntry methods need to be extended to receive an optional dictionary (string,string) of parameters.
QgsSvgCache::replaceElemParams needs to replace any param(__name__) with the corresponding value from the dictionary of parameters.
It also needs to change not only the style XML attributes (for color, width, …) but any part of the SVG code.

Performance implications

If we put apart the case of having tons of different huge SVGs for a same layer with as much parameters combination, we do not expect any performance decrease.

Further improvements

We could also introduce types of parameters to provide optimal widgets (color picker, spin box for numerical values,…)

A parsing of the given SVG could be made to automatically fill the table with the name of parameters. In case the SVG file is data-defined, the parsing could be done across the layer.

Nice proposal!

How would you propose the handle binding these parameters to data defined values?

How would you propose the handle binding these parameters to data defined values?

That's the UX part: a table where you enter the parameters and their values (can be expression). Further improvement proposes an auto fill of this table.

Unfortunately, W3C is not actively working on a parameterized SVG specification. I can ask and see if they could resuscitate the discussion ... but it will take time. Until there are any results there, I think your proposal is fine.

@3nids Looks like creation of dynamic SVG symbols is already available, when we create inline-SVG-symbols using the expression string builder (see my example here: https://gis.stackexchange.com/questions/379437/use-text-diagram-for-labeling-in-qgis/379578#379578)
SVG caching/rendering needs to be tweaked a little bit.

Even embedding images in SVGs is currently possible, when we base64 encode on-the-fly: https://gis.stackexchange.com/questions/380964/qgis-labels-with-html-formating/381241#381241