Animating a gradient

In v7.7.1 is it possible to animate the fill paint of a component using the style customizer? I’d like to have different states trigger different colored gradient fills. However, when I animate anything with a gradient, it reverts to a solid color paint. Thanks!

Yeah, it get’s a little messy. OK, a lot messy, but it can be done. I added three extra Properties to a rectangle, Color1, Color2, and Style. This way you can pick both colors of the gradient via scripting.

if event.propertyName=="Color1": from java.awt import Color from java.awt import GradientPaint o=event.source x1=o.relX y1=o.relY Color1=o.Color1 x2=x1+o.relWidth y2=y1 Color2=o.Color2 o.setFillPaint(GradientPaint(x1,y1,Color1,x2,y2,Color2,1))

When changing the gradient this way, the Fill Paint type becomes unknown, so you have to change it to something it recognizes before yo can do anything further to it. Like copy/paste, or adjust your styles:

Perhaps someone else can chime in and tell me what I’m missing… :scratch:

Here’s a window to look at.
AnimatedGradient_2014-11-25_0850.proj (6.97 KB)

1 Like

Thanks for the reply, Jordan!
Your script works well. :thumb_right:
I was looking to simply include the paint characteristics in a style table, but that doesn’t work. Your workaround, using the java gradientpaint function, works great. It is a little messy how it sets the paint to “unk,” but I may be able to live with that.

Maybe built-in animation for paint styles will be in a future release.

May be who knows how do radial gradient?

I create circle and added to it two custom properties (OrangeColor (type Color), RedColor (type Color)) and wroted this script:

from java.awt import Color
from java.awt import RadialGradientPaint

o = event.source
x1=o.relX
y1=o.relY

Colors=[o.OrangeColor,o.RedColor]
Floats=[0.0,1.0]

o.setFillPaint(RadialGradientPaint(x1,23,o.relWidth/2,Floats,Colors))

It’s work, but it is not that i wanted…

[code]from com.inductiveautomation.ignition.client.util.gui.paints import RelativeLinearGradientPaint
from com.inductiveautomation.ignition.client.util.gui.paints.MultipleGradientPaint import CycleMethod
from java.awt.geom import Point2D

if event.propertyName in [“Color1”,“Color2”]:
rlgp = RelativeLinearGradientPaint(Point2D.Double(0.0,0.5), Point2D.Double(1.0,0.5),[0.0,1.0],[event.source.Color1, event.source.Color2],CycleMethod.NO_CYCLE)
event.source.fillPaint = rlgp[/code]

I guess I need more information

modifying the code in the original window:

[code]if event.propertyName==“Color1”:
from java.awt import Color
from java.awt import RadialGradientPaint

o=event.source
x1=o.relX + o.relWidth/2
y1=o.relY + o.relHeight/2
Color1=o.Color1
Color2=o.Color2
o.setFillPaint(RadialGradientPaint(x1, y1, o.relWidth/2,[0.0, 1.0], [Color1,Color2]))[/code]

Thanks for the code, Jae, I like how it keeps the gradient type in the properties!

EDIT: Nosing around, I can’t seem to find anything for the radial gradient type.

I didn’t realize your post was from 2014 !

[code]com.inductiveautomation.ignition.client.util.gui.paints.RadialGradientPaint

RadialGradientPaint(float cx, float cy, float radius, float[] fractions, java.awt.Color[] colors, MultipleGradientPaint.CycleMethod cycleMethod)[/code]

It’s still good information. I’ll update my window export above to reflect it. But first… lunch!

Thanks!

i just want to get like that…

Clearly i did something not right when i used

RadialGradientPaint(float cx, float cy, float radius, float[] fractions, java.awt.Color[] colors, MultipleGradientPaint.CycleMethod cycleMethod)[/code]

Here is my script:

code
#Circle position = x=50, y =50, width=25, height=25, WhiteColor and BlueColor are custom properties of this circle

import com.inductiveautomation.ignition.client.util.gui.paints
o=event.source

rgp=RadialGradientPaint(o.relWidth/2,o.relHeight/2,25,[0.0,1.0],[o.BlueColor,o.WhiteColor],CycleMethod.NO_CYCLE)
o.SetFillPaint=rgp[/code]

Two things I could see:

  • setFillPaint is a method, so you need to call it like a function.
  • you will need to add relX and relY to the coordinates to center the gradient.

[code]from com.inductiveautomation.ignition.client.util.gui.paints import RadialGradientPaint
from com.inductiveautomation.ignition.client.util.gui.paints.MultipleGradientPaint import CycleMethod

o=event.source
rgp=RadialGradientPaint(o.relX+o.relWidth/2, o.relY+o.relHeight/2, 25, [0.0,1.0], [o.WhiteColor, o.BlueColor], CycleMethod.NO_CYCLE)
o.setFillPaint(rgp)[/code]

:prayer: Thanks. It’s working!

The problem with the above solution is that it causes the Fill Paint to have a value “unk”. If you try to save the project with that as the Fill Paint. The save will throw a serialization error. If instead you use “RelativeRadialGradientPaint” it will identify the gradient correctly and save with no problem.

if event.propertyName == "EdgeColor" or event.propertyName == "CenterColor":
	from com.inductiveautomation.ignition.client.util.gui.paints import RelativeRadialGradientPaint
	from com.inductiveautomation.ignition.client.util.gui.paints.MultipleGradientPaint import CycleMethod
	from java.awt.geom import Point2D
	o=event.source
	rrgp=RelativeRadialGradientPaint(Point2D.Double(0.5,0.5), Point2D.Double(0.0,0.0), Point2D.Double(0.0,0.0), Point2D.Double(0.0,0.0), [0.0,1.0], [o.CenterColor, o.EdgeColor], CycleMethod.NO_CYCLE)
	o.fillPaint = rrgp
1 Like

Revisiting this old topic…

I’d like to use jpark’s technique so that I avoid the “unk” fill problem. Where can I find documentation on the inductive automation RelativeLinearGradientPaint function? I’d like to be able to modify the gradient to add more stops and it seems to be quite different from the java gradient.

https://docs.oracle.com/javase/7/docs/api/java/awt/RadialGradientPaint.html

Hi jpark, thanks. That gives the docs for radial gradient paint and I can get similar docs from Oracle for linear gradient paint. However, the arguments for inductive automation’s “relative” linear gradient paint are different. From trial and error, I know that it wants either 5 or 7 arguments and that, if you use 7 arguments, the third one must be a floating-point numeric. I’m just not clear how to take your

rlgp = RelativeLinearGradientPaint(Point2D.Double(0.0,0.5), Point2D.Double(1.0,0.5),[0.0,1.0],[event.source.Color1, event.source.Color2],CycleMethod.NO_CYCLE)

and modify it to add more stops.

1 Like

For anyone who is interested in this topic, here are the arguments for RelativeLinearGradient:

public RelativeLinearGradientPaint(java.awt.geom.Point2D start,
                                   java.awt.geom.Point2D end,
                                   float[] fractions,
                                   java.awt.Color[] colors,
                                   MultipleGradientPaint.CycleMethod cycleMethod,
                                   MultipleGradientPaint.ColorSpaceType colorSpace,
                                   java.awt.geom.AffineTransform gradientTransform)
Constructs a LinearGradientPaint.
Parameters:
start - the gradient axis start Point2D in user space
end - the gradient axis end Point2D in user space
fractions - numbers ranging from 0.0 to 1.0 specifying the distribution of colors along the gradient
colors - array of colors corresponding to each fractional value
cycleMethod - either NO_CYCLE, REFLECT, or REPEAT
colorSpace - which color space to use for interpolation, either SRGB or LINEAR_RGB
gradientTransform - transform to apply to the gradient

I was able to add gradient “stops” by adding to the fractions and colors arrays.

1 Like

Great thread guys. Thanks for seeing through to the end MCC

@weertske This method works great! Except I'm having one issue.

The script for coloring the shape with a gradient fill only occurs when one of the color changes. I've linked those colors to a boolean parameter, and then tied to that to an OPC tag. The issue is that the filling is triggered on the boolean parameter change, so when when I first navigate to a window, everywhere there is an instance of this shape, it just has the default coloring until a state change occurs. Seeking ideas on how to trigger the filling when graphic is first opened so that the initial state will be set properly.

Sorry, I am a little tied up with other projects right now so I suggest you direct this at some of the other members of this thread. Of the top of my head I would tie a script to on window opened event and toggle the boolean.