譯自《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。