译自《Shapes and Animation》
形状和动画
JavaFX带有几乎表示任何几何形状的节点,以及一个Path
节点,它提供组装和管理几何路径所需的工具(以创建自定义形状)。 JavaFX还具有动画支持,逐渐改变Node
属性,创建两个状态之间的视觉转换。 TornadoFX旨在通过构建器构造来简化所有这些功能。
形状基础(Shape Basics)
形状构建器的每个参数都是可选的,在大多数情况下,默认值为0.0 。 这意味着您只需要提供您关心的参数。 构建器具有每个形状的大多数属性的位置参数,其余的可以设置在随后的函数块中。 因此,这些都是创建矩形的有效方式:
rectangle {
width = 100.0
height = 100.0
}
rectangle(width = 100.0, height = 100.0)
rectangle(0.0, 0.0, 100.0, 100.0)
您选择的形式是偏好的问题,但显然需要考虑到您编写的代码的易读性。 为了清楚起见,本章中的示例指定了代码块中的大部分属性,除非没有代码块支持或参数是非常自明的。
在父项内定位
大多数形状构建器可以让您选择在父项中指定形状的位置。 这是否有任何影响取决于父节点。 除非您在形状上调用setManaged(false)
,否则HBox
不会关心您指定的x
和y
坐标。 但是,Group
控件将会关心这一点。 以下示例中的截图将通过在一个Group
周围包装一个StackPane
,并最后在该Group
内创建形状,如下所示。
class MyView: View() {
override val root = stackpane {
group {
//shapes will go here
}
}
}
长方形(Rectangle)
Rectangle
定义了一个矩形,其中可选的大小和位置在父项中。 可以使用arcWidth
和arcHeight
属性指定圆角(图9.1)。
rectangle {
fill = Color.BLUE
width = 300.0
height = 150.0
arcWidth = 20.0
arcHeight = 20.0
}
弧形(Arc)
Arc
表示由中心(center),起始角度(start angle),角度范围(angular extent,以度计的弧度)和圆弧类型(arc type, OPEN, CHORD或ROUND )定义的弧形对象(图9.2)
arc {
centerX = 200.0
centerY = 200.0
radiusX = 50.0
radiusY = 50.0
startAngle = 45.0
length = 250.0
type = ArcType.ROUND
}
圆圈(Circle)
Circle
表示具有指定radius
和center
的圆。
circle {
centerX = 100.0
centerY = 100.0
radius = 50.0
}
CubicCurve
CubicCurve
表示(x,y)
坐标空间中的立方贝塞尔参数曲线段(cubic Bézier parametric curve segment)。 使用指定点(controlX1
, controlY1
) 和(controlX2
, controlY2
) 作为Bézier控制点,绘制与指定的坐标(startX
, startY
)和(endX
, enfY
)相交的曲线。
cubiccurve {
startX = 0.0
startY = 50.0
controlX1 = 25.0
controlY1 = 0.0
controlX2 = 75.0
controlY2 = 100.0
endX = 150.0
endY = 50.0
fill = Color.GREEN
}
椭圆(Ellipse)
Ellipse表示具有指定大小和位置参数的椭圆。
ellipse {
centerX = 50.0
centerY = 50.0
radiusX = 100.0
radiusY = 50.0
fill = Color.CORAL
}
线(Line)
线是相当直接的。 提供开始和结束坐标以绘制两点之间的一条线。
line {
startX = 50.0
startY = 50.0
endX = 150.0
endY = 100.0
}
折线(Polyline)
Polyline
由分段点数组(an array of segment points)定义。 Polyline
与Polygon
类似,但不会自动关闭。
polyline(0.0, 0.0, 80.0, 40.0, 40.0, 80.0)
QuadCurve
Quadcurve
表示(x,y)坐标空间中的二次Bézier参数曲线段(quadratic Bézier parametric curve segment)。 使用指定点(controlX
, controlY
) 作为Bézier控制点,绘制与指定坐标(startX
, startY
)和 (endX
, endY
)相交的曲线。
quadcurve {
startX = 0.0
startY = 150.0
endX = 150.0
endY = 150.0
controlX = 75.0
controlY = 0.0
fill = Color.BURLYWOOD
}
SVGPath
SVGPath
表示通过从String
解析SVG路径数据(SVG path data)构造的形状。
svgpath("M70,50 L90,50 L120,90 L150,50 L170,50 L210,90 L180,120 L170,110 L170,200 L70,200 L70,110 L60,120 L30,90 L70,50") {
stroke = Color.DARKGREY
strokeWidth = 2.0
effect = DropShadow()
}
路径(Path)
Path
代表一个形状,并提供基本的构造和管理几何路径所需的设施。 换句话说,它可以帮助您创建自定义形状。 以下帮助函数可用于构建路径:
moveTo(x, y)
hlineTo(x)
vlineTo(y)
quadqurveTo(controlX, controlY, x, y)
lineTo(x, y)
arcTo(radiusX, radiusY, xAxisRotation, x, y, largeArcFlag, sweepFlag)
closepath()
path {
moveTo(0.0, 0.0)
hlineTo(70.0)
quadqurveTo {
x = 120.0
y = 60.0
controlX = 100.0
controlY = 0.0
}
lineTo(175.0, 55.0)
arcTo {
x = 50.0
y = 50.0
radiusX = 50.0
radiusY = 50.0
}
}
动画
JavaFX具有通过逐渐更改其一个或多个属性来动画化任何Node
的工具。 在JavaFX中创建动画有三个组件。
Timeline
- 以指定顺序执行的一系列KeyFrame
项
KeyFrame
- 指定在一个或多个节点上的一个或多个可写属性(通过KeyValue
)的值改变的(specifying value changes)“快照”
KeyValue
- 将Node
属性与将被“转换(transitioned)”到的值配对
KeyValue
是JavaFX动画的基本构建块。 它指定一个属性和“新值”,它将逐渐转换到该新值。 所以如果你有一个Rectangle
, 其rotateProperty()
为0.0
,并且你指定一个KeyValue
,将其改为90.0
度,它会递增地从0.0
改变到90.0
度。 将KeyValue
放在KeyFrame
,这可以指定这两个值之间的动画持续时间。 在这种情况下,我们让它为5
秒。 最后把这个KeyFrame
放在一个Timeline
。 如果您运行下面的代码,您将看到一个rectange
在5秒钟内从0.0
逐渐旋转到90.0
度(图9.1)。
val rectangle = rectangle(width = 60.0,height = 40.0) {
padding = Insets(20.0)
}
timeline {
keyframe(Duration.seconds(5.0)) {
keyvalue(rectangle.rotateProperty(),90.0)
}
}
在给定的KeyFrame
,您可以同时处理该5
秒窗口中的其他属性。 例如,我们可以在Rectangle
旋转时转换arcWidthProperty()
和arcHeightProperty()
(图9.2)。
timeline {
keyframe(Duration.seconds(5.0)) {
keyvalue(rectangle.rotateProperty(),90.0)
keyvalue(rectangle.arcWidthProperty(),60.0)
keyvalue(rectangle.arcHeightProperty(),60.0)
}
}
插值(Interpolators)
您还可以指定一个可以为动画添加微妙效果的Interpolator
。 例如,您可以指定Interpolator.EASE_BOTH
来优化动画开始和结束时的值更改。
val rectangle = rectangle(width = 60.0, height = 40.0) {
padding = Insets(20.0)
}
timeline {
keyframe(5.seconds) {
keyvalue(rectangle.rotateProperty(), 180.0, interpolator = Interpolator.EASE_BOTH)
}
}
循环和自动反转(Cycles and AutoReverse)
您可以修改timeline()
其他属性,如cycleCount
和autoReverse
。 cycleCount
将重复动画指定次数,且将isAutoReverse
设置为true
将导致每个循环返回。
timeline {
keyframe(5.seconds) {
keyvalue(rectangle.rotateProperty(), 180.0, interpolator = Interpolator.EASE_BOTH)
}
isAutoReverse = true
cycleCount = 3
}
要无限期重复动画,请将cycleCount
设置为Timeline.INDEFINITE
。
速记动画(Shorthand Animation)
如果要为单个属性设置动画,您可以快速地将其动画化,而无需声明timeline()
, keyframe()
和keyset()
。 调用该interoplator
的animate()
扩展函数,并提供endValue
, duration
,以及可选的interoplator
。 如果您只是一个属性动画,这会更短,更干净。
rectangle.rotateProperty().animate(endValue = 180.0, duration = 5.seconds)
总结
在本章中,我们介绍了形状和动画的构造器。 我们没有覆盖JavaFX的Canvas
因为这超出了TornadoFX框架的范围。 它可以容易地占用多个章节。 但是,形状和动画应该能允许您为大多数任务执行基本的自定义图形。
现在,我们对TornadoFX构建器的覆盖范围到此结束。 接下来,我们将为那些需要使用它的人介绍FXML。