Scaling a rectangle from the center

Hi guys.

Im trying to adjust the width some rectangles based on a PLC tag in Vision.
The problem is: When I tie a tag to the width property, the rectangle grows and shrinks, but the anchor point is to the top left. Is there a way to make it understand the center is the anchor point?

I tried to tie an expression to the x position to move the rectangle over based on width, so that it still sits "center" of where I need it to be. However, it seems to only update when it feels like it. During testing, I'm not even using a tag. Just an expression on the X property based on the width property and typing in the width manually. It seems to execute on the 2nd or 3rd change only, and when tied to a tag, doesn't move.

Customer is adamant we replicate their existing animations from a Wonderware project.

Any advice?

Show your code! Format it properly with the </> button.

OK.
There isn't much code.
I have this box. It can go from 0-100 on width.
Center position is 180-230 depending on the width of the box.

So, here's my box.
image

I am manually typing in the width value.
image

This is my expression tied to the x position

If i change my width to 50, the property expression doesnt execute
image
image

But now if i enter, say 50.1, it exectues
image
image

What is the trick to controlling the trigger on an expression? In the end my width will be tag driven. But for testing and positioning, I'm starting off just fat fingering numbers in.

Events coming from shapes don't work that well. So, I feel ya.

I would make two custom properties at the container level. One to hole the centerline absolute x position and one for the width. bind properties and expressions to those, instead.

{Root Container.coilCenterLine} - {Root Container.coilWidth}/2

1 Like

I am going to give this a shot. Thank you.

The animation properties in Ignition really aren't there compared to other platforms..

That's more of an underlying Java Swing thing. Events seem to work better top-down than bottom-up, in general.

1 Like

I tried your method of using custom properties at the container level. It seemed promising during development, but once I roll the screen out, the same problem persists.
image


image

I guess I'll just try to force it by using a tag or counter in the PLC. It just refuses to update at a controllable time.

I would use a paintable canvas and draw everything. That is going to be the best method for full control that you'll get.

2 Likes

Had a bit of free time today, so I whipped this up. To show how this would work with a paintable canvas. Obviously I've used sliders here, but tag values can easily be used in place of those. I created three custom properties on the paintable canvas component and bound them to the sliders. Doing that the canvas will automatically repaint when the properties change.

rects

Here is the script in the repaint event on the canvas.

from java.awt import Color
from java.awt.geom import Rectangle2D as Rect
from java.awt.geom import Point2D as Point

#save the graphics object, really so you can type less
g = event.graphics

#all graphics are drawn with an assumption of 100 x 100 px size
#scalling is applied later prior to painting

#base rectangle
#graphics are drawn with 0,0 being at the top left corner
#Postive y direction is down

#base rectangle position
baseRectLoc = Point.Float(event.source.baseXPosition,80)

#base rectangle
baseRect = Rect.Float(baseRectLoc.x,baseRectLoc.y, event.source.baseWidth, 20)

#carried rectangle
#calculate x position of rect
#because we want the centers of the rectangles to always be aligned then we need to account for
#the width of the carried rectangle.
carriedLoc = Point.Float()
carriedWidth = event.source.carriedWidth
carriedLoc.setLocation((baseRect.centerX - (carriedWidth / 2.0)), 10)

carriedRect = Rect.Float(carriedLoc.x, carriedLoc.y, carriedWidth, 70)

# Scale graphics to actual component size
dX = (event.width-0.01)/100.0
dY = (event.height-0.01)/100.0
g.scale(dX,dY)

#paint the rectangles
g.setPaint(Color.GRAY)
g.fill(baseRect)
g.setPaint(Color.GREEN)
g.fill(carriedRect)
2 Likes