Tip: how to create SVGs and changing the fill color dynamically

This may be helpful in creating custom symbols for perspective. SVGs allow changing of fill colors, etc., dynamically.

  1. Create your SVG using your favourite program. In this example I’ve used Inkscape.
  • Hit Ctrl-Shift-D to set the document properties and set the units and grid. I chose a 1 mm grid. Take a little care with this so that you can be consistent with your work.

  • Draw your symbol. Use the Z-order buttons to push objects back and forwards in the stack.
  • Hit Ctrl-Shift-F to edit the fill and stroke of the objects. Pick a “wrong” color so that you can be sure your changes are working later in Ignition.
  • Hit Ctrl-Shift-O to name the objects. The names you assign here will show up in Perspective.
  • Select the objects and hit Ctrl-Shift-R to set the bounding box for the objects. This will crop the viewBox tight to the size of your graphic.
  • Save As … plain SVG. (I didn’t test whether or not Perspective can handle Inkscapes SVG format which contains extra Inkscape info.)
  1. Drag and drop the image using File Explorer onto a Perspective view.
  2. Create a custom property. Here I’ve set the fill color using on of the theme colours.

Perspective Inkscape pump step 2

  1. In step 3 in the image above create a binding to whatever will drive the color property. Note again that I’m using theme colors rather than hard code them.

  1. Finally, bind each of the SVG element’s fill properties to the custom property we set above. (You could skip the custom property completely but I think doing it this way means you only have to set it once at a high level.)

I hope someone finds this useful.

12 Likes

Another option that might not be immediately obvious is to do this with style classes. Same concept: create a central binding point that will execute the logic of which style class(es) to use, create a “style” object within each element of the svg, add the “classes” property to the style element, and bind the value to your central style class logic. You will have to delete any fill or stroke properties that you do not want overridden from what is in your style class such as paint, width, or in my case I removed the stroke and fill objects entirely:

image

Also of note, only the “Shape” style class properties are going to apply here.

1 Like

Another useful option is to apply the style: vector-effect: non-scaling-stroke which will keep your stroke the same width no matter the scaling of the SVG. Unfortunately this needs to be applied to every element

2 Likes

Thanks for your tip. I’ve got it working on the “Pumping” label in the gif below but can’t get it to work on the circle fill.

Perspective pumping

Both are using the pumping style class and if I set the whole object’s style | classes to pumping the circle’s box background flashes green.

Can you see what’s wrong with my setup? (I notice I have a second level of elements and that you don’t.)

Links:

What’s in your pumping style? To style SVG fills, you need to use the shape.fill** (edited) in the Style (not background-color)

4 Likes

or fill instead of backgroundcolor

I think that’s probably what I meant, but in the Style dialogue it’s stashed under “Shape”

ah i never have rly used the style dialogue thingy xd expect to open background image for injection xD

You don’t use Perspective Styles then?

The style classes? i guess i do, guess my co)workers made the basic ones. And i only make them for the weird hacky styles xd

Yes, setting the Style | Class shape fill solved the problem. Thanks!

Haha, I probably should have been a little more clear with the last line of my reply, but @nminchin wrote what I meant.

Oh, I completely missed the last line of your reply :grinning_face_with_smiling_eyes:

Would you say it is a must?

I'm still a beginner on perspective so it has been challenging.

@tupanaster
Yes. You won’t be able to do a number of things without them for example hover animations, animations in general eg from on colour to another. But most importantly, they offer style standardisation to your project for things like button look and feel, device state colours, styling of analogue values, setpoints, font sizing, etc. etc.
I combine styles with a css theme to define my colours in css variables and use those variables in my perspective styles. You can see examples in the project themes folder on the gateway, I’ll copy a folder path in later on. There’s also a read me in there as well

For my first demo (which I' m still working on) I just grabbed one of the templates to work with. I removed the color variable from some styles in the Styles folder and hardcoded the ones I want to use. I hope to understand this part better for the next demo and before my first real project.

Going back to SVG drawings, it would be nice to wrap up tips and tricks in another post like this

My imported SVG from Inkscape have tons of errors. Even after exporting as optimized SVG. yesterday I even got a new weird error; the color in the designer was different from the one showed in the browser. Like if it was null.

Color was changed just as this post explained, drilling down to the fill or color property to change colors. But in the browser it looks like a null color or something.

Designer:

Property transform

Browser:
image

It also used to look as null in the workstation but today it looks the same... A bit weird

this.props.Fill should go to custom props

So I created a custom prop and bind it to the color. Same result

On web browser:
image

heh weird, could you provide the json of the svg so i can test some stuff?

Here it is.

JSON code

[
{
“type”: “ia.shapes.svg”,
“version”: 0,
“props”: {
“viewBox”: “0 0 140 120”,
“elements”: [
{
“elements”: [
{
“d”: “m8.6705 44.8h121.91”,
“fill”: {
“paint”: “#C0C0C0
},
“name”: “path”,
“stroke”: {
“paint”: {
“gradientTransform”: “matrix(0 0 0 0 -15897 -329.96)”,
“stops”: [
{
“offset”: “0”,
“stopColor”: “#55555a
}
],
“type”: “linear”
}
},
“type”: “path”
},
{
“fill”: {
“paint”: {
“gradientTransform”: “matrix(0 0 0 0 -15897 -415.11)”,
“stops”: [
{
“offset”: 0
}
],
“type”: “linear”
}
},
“height”: “59.583”,
“name”: “rect”,
“transform”: “scale(-1)”,
“type”: “rect”,
“width”: “121.91”,
“x”: “-131.13”,
“y”: “-104.79”
},
{
“d”: “m4 110h132v-100h-5v95h-122v-95h-5z”,
“fill”: {
“paint”: {
“gradientTransform”: “matrix(2.3872 0 0 4.7384 4109.4 3902.3)”,
“stops”: [
{
“offset”: “0”,
“stopColor”: “#d9d1c8
}
],
“type”: “linear”
},
“rule”: “evenodd”
},
“name”: “path”,
“stroke”: {
“dasharray”: “1, 1”,
“linecap”: “square”,
“paint”: {
“gradientTransform”: “matrix(0 0 0 0 -15897 -415.11)”,
“stops”: [
{
“offset”: “0”,
“stopColor”: “#9c9e9f
}
],
“type”: “linear”
}
},
“type”: “path”
},
{
“d”: “m9.0329 14.767h121.26v-4.6842h-121.26z”,
“fill”: {
“paint”: {
“gradientTransform”: “matrix(2.3872 0 0 4.7384 4109.4 3902.3)”,
“stops”: [
{
“offset”: “0”,
“stopColor”: “#d9d1c8
}
],
“type”: “linear”
},
“rule”: “evenodd”
},
“name”: “path”,
“stroke”: {
“dasharray”: “1.16609, 1.16609”,
“linecap”: “square”,
“paint”: {
“gradientTransform”: “matrix(0 0 0 0 -15897 -415.11)”,
“stops”: [
{
“offset”: “0”,
“stopColor”: “#9c9e9f
}
],
“type”: “linear”
}
},
“type”: “path”
}
],
“name”: “group”,
“type”: “group”
}
],
“Fill”: “blue”
},
“meta”: {
“name”: “OPT Sump 2”
},
“position”: {
“height”: 1,
“width”: 1
},
“custom”: {
“customPropColor”: “stronger gray”
},
“propConfig”: {
“props.elements[0].elements[1].fill.paint.stops[0].stopColor”: {
“binding”: {
“config”: {
“path”: “this.custom.customPropColor”
},
“transforms”: [
{
“fallback”: “#000000”,
“inputType”: “scalar”,
“mappings”: [
{
“input”: “stronger gray”,
“output”: “#A0A0A0
}
],
“outputType”: “color”,
“type”: “map”
}
],
“type”: “property”
}
}
}
}
]

Edit 2:

Formatted JSON string
[
  {
    "type": "ia.container.coord",
    "version": 0,
    "props": {
      "mode": "percent",
      "aspectRatio": "1:1"
    },
    "meta": {
      "name": "root"
    },
    "position": {},
    "custom": {},
    "children": [
      {
        "type": "ia.shapes.svg",
        "version": 0,
        "props": {
          "viewBox": "0 0 140 120",
          "elements": [
            {
              "elements": [
                {
                  "d": "m8.6705 44.8h121.91",
                  "fill": {
                    "paint": "#C0C0C0"
                  },
                  "name": "path",
                  "stroke": {
                    "paint": {
                      "gradientTransform": "matrix(0 0 0 0 -15897 -329.96)",
                      "stops": [
                        {
                          "offset": "0",
                          "stopColor": "#55555a"
                        }
                      ],
                      "type": "linear"
                    }
                  },
                  "type": "path"
                },
                {
                  "fill": {
                    "paint": {
                      "gradientTransform": "matrix(0 0 0 0 -15897 -415.11)",
                      "stops": [
                        {
                          "offset": 0
                        }
                      ],
                      "type": "linear"
                    }
                  },
                  "height": "59.583",
                  "name": "rect",
                  "transform": "scale(-1)",
                  "type": "rect",
                  "width": "121.91",
                  "x": "-131.13",
                  "y": "-104.79"
                },
                {
                  "d": "m4 110h132v-100h-5v95h-122v-95h-5z",
                  "fill": {
                    "paint": {
                      "gradientTransform": "matrix(2.3872 0 0 4.7384 4109.4 3902.3)",
                      "stops": [
                        {
                          "offset": "0",
                          "stopColor": "#d9d1c8"
                        }
                      ],
                      "type": "linear"
                    },
                    "rule": "evenodd"
                  },
                  "name": "path",
                  "stroke": {
                    "dasharray": "1, 1",
                    "linecap": "square",
                    "paint": {
                      "gradientTransform": "matrix(0 0 0 0 -15897 -415.11)",
                      "stops": [
                        {
                          "offset": "0",
                          "stopColor": "#9c9e9f"
                        }
                      ],
                      "type": "linear"
                    }
                  },
                  "type": "path"
                },
                {
                  "d": "m9.0329 14.767h121.26v-4.6842h-121.26z",
                  "fill": {
                    "paint": {
                      "gradientTransform": "matrix(2.3872 0 0 4.7384 4109.4 3902.3)",
                      "stops": [
                        {
                          "offset": "0",
                          "stopColor": "#d9d1c8"
                        }
                      ],
                      "type": "linear"
                    },
                    "rule": "evenodd"
                  },
                  "name": "path",
                  "stroke": {
                    "dasharray": "1.16609, 1.16609",
                    "linecap": "square",
                    "paint": {
                      "gradientTransform": "matrix(0 0 0 0 -15897 -415.11)",
                      "stops": [
                        {
                          "offset": "0",
                          "stopColor": "#9c9e9f"
                        }
                      ],
                      "type": "linear"
                    }
                  },
                  "type": "path"
                }
              ],
              "name": "group",
              "type": "group"
            }
          ],
          "Fill": "blue"
        },
        "meta": {
          "name": "OPT Sump 2"
        },
        "position": {
          "height": 1,
          "width": 1
        },
        "custom": {
          "customPropColor": "stronger gray"
        },
        "propConfig": {
          "props.elements[0].elements[1].fill.paint.stops[0].stopColor": {
            "binding": {
              "config": {
                "path": "this.custom.customPropColor"
              },
              "transforms": [
                {
                  "fallback": "#000000",
                  "inputType": "scalar",
                  "mappings": [
                    {
                      "input": "stronger gray",
                      "output": "#A0A0A0"
                    }
                  ],
                  "outputType": "color",
                  "type": "map"
                }
              ],
              "type": "property"
            }
          }
        }
      },
      {
        "type": "ia.display.label",
        "version": 0,
        "props": {
          "style": {
            "backgroundColor": "#A0A0A0"
          }
        },
        "meta": {
          "name": "Label"
        },
        "position": {
          "x": 0.0641,
          "y": 0.3849,
          "height": 0.44,
          "width": 0.8714
        },
        "custom": {}
      }
    ]
  }
]