Sorry, time got away from me.
Script below.
obj
is a copy of the "SVG" in the View, converted into a Py Object with json.loads
/ system.util.jsonDecode
The ATTR_LOOKUP
is a conversion table (dictionary) of Ignition styles to its corresponding SVG style.
EDIT: Tested and working in the script console, although you'll need the clipboard functions. I've posted them elsewhere on the forum
import xml.etree.cElementTree as et
import json
import copy
def extract_svg_from_view(obj):
#json_str = clipboard.getClipboard()
#'[{ "type": "ia.shapes.svg", "version": 0, "props": { "viewBox": "0 0 185 527.99", "elements": [{ "type": "path", "name": "rect933", "d": "m92.5 5c-43.75 0-87.5 30.69-87.5 92.07v425.92h175v-425.92c0-61.38-43.75-92.07-87.5-92.07z", "fill": { "paint": "#fff" }, "stroke": { "paint": "#000", "linecap": "round", "width": "10" } }, { "type": "path", "name": "rect933-3", "d": "m92.5 5c-43.75 0-87.5 30.69-87.5 92.07v425.92h175v-425.92c0-61.38-43.75-92.07-87.5-92.07z", "fill": { "paint": "#fff" }, "stroke": { "paint": "#000", "linecap": "round", "width": "10" } }, { "type": "group", "name": "g7299", "fill": { "paint": "#ff2a2a" }, "stroke": { "paint": "#000", "linecap": "round", "width": "10" }, "elements": [{ "type": "circle", "name": "circle7295", "cx": "69.758", "cy": "157.43", "r": "64.685" }, { "type": "circle", "name": "path7213", "cx": "92.5", "cy": "263.99", "r": "64.685" } ] } ] }, "meta": { "name": "TEST_Export" }, "position": { "basis": "20px" }, "custom": {} } ] '
#svg_obj = json.loads(json_str)
svg_obj = obj[0] # assume that the obj passed in is a copied "SVG" from a Perspective View which adds the SVG definition into a single item array. We want the item
viewbox = svg_obj['props']['viewBox']
elements = svg_obj['props']['elements']
ATTR_LOOKUP = {}
ATTR_LOOKUP['name'] = 'id'
ATTR_LOOKUP['fill.paint'] = 'fill'
ATTR_LOOKUP['fill.opacity'] = 'opacity'
ATTR_LOOKUP['stroke.paint'] = 'stroke'
ATTR_LOOKUP['style.stroke'] = 'stroke'
ATTR_LOOKUP['stroke.linecap'] = 'stroke-linecap'
ATTR_LOOKUP['stroke.width'] = 'stroke-width'
ATTR_LOOKUP['style.strokeWidth'] = 'stroke-width'
ATTR_LOOKUP['style.vector-effect'] = 'vector-effect'
doc = et.Element('svg', viewBox=viewbox, version='1.1', xmlns='http://www.w3.org/2000/svg')
not_included_SVG_elements = []
def addElements(xmlobj, elements):
for element in elements:
if 'type' in element:
attrs_dict = {}
# collect the attributes for the current SVG element are store them in a dictionary
for attr_name in element:
# exclude any nested elements as they need to be added later. These are not added as attributes
if attr_name != 'elements':
attr = element[attr_name]
# if the attribute is a dict in Ignition, then the dict will contain the actual attribute names
if isinstance(attr, dict):
for prop_name in attr:
svg_prop_name = ATTR_LOOKUP.get('{}.{}'.format(attr_name, prop_name), 'UNSET')
if svg_prop_name == 'UNSET':
not_included_SVG_elements.append('{}.{}'.format(attr_name, prop_name))
svg_prop_val = attr[prop_name]
attrs_dict[svg_prop_name] = svg_prop_val
else:
attrs_dict[ATTR_LOOKUP.get(attr_name, attr_name)] = attr
element_name = attrs_dict['type']
if element_name == 'group':
element_name = 'g'
xmlobj_attr = et.SubElement(xmlobj, element_name, **attrs_dict)
if 'elements' in element:
attr_elements = copy.deepcopy(element['elements'])
addElements(xmlobj_attr, attr_elements)
addElements(doc, elements)
#print ET.tostring(doc, encoding='utf8', method='xml')
if not_included_SVG_elements != []:
print "Copied to clipboard, but some SVG attributes are missing mapping. These have not been extracted {}".format(not_included_SVG_elements)
return et.tostring(doc)
json = shared.util.clipboard.readText()
obj = system.util.jsonDecode(json)
svg = extract_svg_from_view(obj)
shared.util.clipboard.writeText(svg)