Binding color for all elements in embedded SVG

Summary:
Is it possible to set a single indirect binding for the color of all elements in a group within an embedded SVG, without having to bind each element individually?

Detail:
I watched Michael Schmid’s excellent video on creating and animating custom Perspective graphics using Inkscape and SVG files, and saw a ton of potential applications for these custom graphics.

I draw a mockup of one of my company’s process lines and included 200 overlaid ellipses I intended on animating depending on the status of that location. I have a tag holding an array of 200 bools, the status of each respective location. The tag is mapped to a custom property of the SVG, and I’d like to link the color of each ellipse to one item in the array so that the ellipse would be green if the item is true, and grey if false.

However, I haven’t been able to find a way to set a binding on the color for ALL elements, just each element individually. I feel like there has to be a way to set “color for element [i] = array[i]” with a map transform, but haven’t found one. I’m still fairly new to Ignition though, so it’s very possible I’ve missed something.

Good question. I was thinking that you could do an expression binding to the locationStatus of the form
`{this.props.items[{this.props.index}]}’ where the index would be the SVG element array number. If you could get this to work then you could define your first variable and duplicate 200 times. I can’t find any way to extract the number of the PROPS.elements though. Maybe someone else can come up with a way.

You can absolutely do a map between your byte array and the elements of your SVG group (assuming they have the same number of indices). Below I’m doing a tag binding to a tag that contains my byte array, then using a script transform where I’m referencing the SVG’s elements list, looping through it, and using the pass by reference quality of each element (which more or less act like python dictionaries here) to assign values to their fill colors based on the value of the corresponding index in the byte array.

It might be a better idea to create a new list, make a copy of each element, modify the fill color of the copy, and append the copy to your new list before replacing the entire elements array with your new list, but this was fast and worked well enough. Here’s the script transform I used, though you’ll have to change the reference to where your SVG elements are coming from:

elements = self.props.elements[1].elements
for index,element in enumerate(elements):
	if value[index]:
		element['fill']['paint'] = 'red'
	else:
		element['fill']['paint'] = 'limegreen'
return value
1 Like

Thanks for the replies!

I ended up going a slightly different route than your recommendation, but it seems to be working well. I’m including a description below for feedback/critique on my solution, and also in case it helps anyone else in the future.

I wrote a valueChanged script on my locStatus array to send out a perspective message calling a message handler on the SVG, which in turn called a custom method on the component. The custom method did basically the same as Swolnisty’s solution, and indexed through both the elements and the array and applied a new color to each item.

Pretty sure the process could be streamlined further. This is the first time I’ve used the message handler system but it seems very useful, it reminds me a lot of the signal-slot system in PyQt5.

Thanks for the help!

2 Likes