Статьи

Кто Zoomin ‘Кто? Масштабирование в скомпилированном скрипте JavaFX

В сообщении « Spinning Wheel Got to Go» я показал вам некоторые основные анимации в контексте колеса, которые можно использовать для выбора победителя. Теперь я хотел бы показать вам модификацию, которая предусматривает увеличение части колеса, чтобы аудитория могла видеть имена более четко, когда колесо вращается. Вот скриншот колеса с некоторыми из лучших рок-песен, включая исполнителей, которые их исполняли:

[Img_assist | NID = 755 | название = | убывание = | ссылка = нет | Align = нет | ширина = 500 | высота = 469]

Обратите внимание, что в нижней левой части колеса есть зеленый квадрат. Нажатие на этот квадрат в любое время (например, во время вращения колеса) заставляет колесо увеличивать часть колеса, как показано ниже. Повторное нажатие на квадрат заставляет колесо вернуться к своему первоначальному размеру.

[Img_assist | NID = 756 | название = | убывание = | ссылка = нет | Align = нет | ширина = 500 | высота = 469]

Использование масштабного преобразования для увеличения части графического узла

В приведенном ниже списке показана обновленная версия WinnerWheelJFX.fx, в которую включена эта функция масштабирования. Файл WinnerWheelExample.fx не изменился, и вы можете найти этот файл в посте, указанном выше.

/*
* WinnerWheelJFX.fx - A wheel with names on it that spins
* and lands on a random name. This will
* be used initially by Java Users Groups
* to give a away door prizes. It will be
* improved upon over time, serving as an
* example of compiled JavaFX 2D graphics
* and animation.
*
* Note: The compiled JavaFX Script Key-Frame
* implementation isn't complete, so the
* animation syntax is more verbose than it
* will be in the near future.
*
* Initially developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
*/
import javafx.ui.*;
import javafx.ui.animation.*;
import javafx.ui.canvas.*;
import java.io.BufferedReader;
import java.io.StringReader;
import java.lang.Math;
import java.lang.System;
import com.sun.javafx.runtime.PointerFactory;

public class WinnerWheelJFX extends CompositeNode {
public attribute names:String[];
public attribute chosenName:String;
public attribute chosenIdx:Integer;
public attribute running:Boolean = true;

public attribute zoomed:Boolean;

private static attribute maxNames = 60;
private attribute dlg:Dialog;
private attribute rand:Number;
private attribute stopValue = 1100;
private attribute a:Integer on replace (olda) {
chosenIdx = (((a * rand) % 360) / 360.0 * sizeof names).intValue();
chosenName = names[chosenIdx];
if (a >= stopValue) {
running = false;
MessageDialog {
title: "And the Winner Is..."
visible: true
message: chosenName
}
}
}
private attribute pf = PointerFactory {};
private attribute bpa = bind pf.make(a);
private attribute pa = bpa.unwrap();
private attribute interpolate = NumberValue.LINEAR;
private attribute t =
Timeline {
keyFrames: [
KeyFrame {
keyTime: 0s;
keyValues:
NumberValue {
target: pa;
value: 0;
interpolate: bind interpolate
}
},
KeyFrame {
keyTime: 15s;
keyValues:
NumberValue {
target: pa;
value: 700;
interpolate: bind interpolate
}
},
KeyFrame {
keyTime: 30s;
keyValues:
NumberValue {
target: pa;
value: stopValue
interpolate: bind interpolate
}
}
]
};

public function spin() {
running = true;
rand = Math.random() + .5;
interpolate = NumberValue.LINEAR;
t.start();
}
public function composeNode():Node {
var margin = 20;
var canvas = getCanvas();
var cX = bind canvas.width / 2;
var cY = bind canvas.height / 2;
var rad = bind Math.min(cX, cY) - margin;
var origX = bind cX - rad;
var origY = bind cY - rad;
return
Group {
transform: bind [
Scale.scale(if (zoomed) 1.8 else 1, if (zoomed) 1.8 else 1),
Translate.translate(0, if (zoomed) -0.9 * cY else 0)
]
content: [
Rect {
var zoomFillColor = Color.GREEN
x: bind cX - rad
y: bind cY + rad / 2
width: bind origX / 4
height: bind origX / 4
cursor: Cursor.HAND
fill: bind zoomFillColor
onMouseEntered:
function(cme:CanvasMouseEvent):Void {
zoomFillColor = Color.CYAN;
}
onMouseExited:
function(cme:CanvasMouseEvent):Void {
zoomFillColor = Color.GREEN;
}
onMouseClicked:
function(cme:CanvasMouseEvent):Void {
zoomed = not zoomed;
}
},
Polygon {
var spinFillColor = Color.PURPLE
points: bind [
cX - rad,
cY,
origX / 2,
cY - (origX / 4),
origX / 2,
cY + (origX / 4)
]
cursor: Cursor.HAND
fill: bind spinFillColor
onMouseEntered:
function(cme:CanvasMouseEvent):Void {
spinFillColor = Color.YELLOW;
}
onMouseExited:
function(cme:CanvasMouseEvent):Void {
spinFillColor = Color.PURPLE;
}
onMouseClicked:
function(cme:CanvasMouseEvent):Void {
spin();
}
},
Circle {
var editFillColor = Color.RED
cx: bind cX
cy: bind cY
radius: bind rad / 30
cursor: Cursor.HAND
fill: bind editFillColor
onMouseEntered:
function(cme:CanvasMouseEvent):Void {
editFillColor = Color.BLUE;
}
onMouseExited:
function(cme:CanvasMouseEvent):Void {
editFillColor = Color.RED;
}
onMouseClicked:
function(cme:CanvasMouseEvent):Void {
dlg = Dialog {
var ta = TextArea {
rows: 10
columns: 20
background: Color.WHITE
text: ""
}
modal: true
title: "Enter Up to {maxNames} Names"
visible: true
content: ta
buttons: [
Button {
text: "OK"
defaultButton: true
action:
function():Void {
names = [];
var peopleStr:String = ta.text;
var br = new BufferedReader((new StringReader(peopleStr)));
var line:String;
var i = 0;
while ((line = br.readLine()) <> null and i <= maxNames) {
insert line into names;
i++;
}
dlg.hide();
}
},
Button {
text: "Cancel"
defaultCancelButton: true
action:
function():Void {
dlg.hide();
}
}
]
};
}
},
Group {
transform: bind [
Rotate.rotate(if (running) (a * rand) % 360
else chosenIdx.doubleValue() / sizeof names * 360.0, cX, cY)
]
content: bind [
for (name in names)
Text {
transform: [
Rotate.rotate(((sizeof names - indexof name).doubleValue() /
sizeof names * 360) % 360, cX, cY)
]
font:
Font {
face: FontFace.SANSSERIF
size: 12
style: FontStyle.BOLD
}
fill: if ((indexof name % 3) == 1) Color.RED
else if ((indexof name % 3) == 2) Color.BLUE
else Color.GREEN
x: cX - rad + 5
y: cY
content: "{name}"
}
]
}
]
};
}
}

Особо следует отметить фрагмент кода, показанный ниже, который рисует зеленый прямоугольник на экране, реагирует на события мыши и вызывает масштабирование и перемещение (перемещение) колеса. Обратите внимание, что zoomedэто логический атрибут, определенный ранее в листинге.

        transform: bind [
Scale.scale(if (zoomed) 1.8 else 1, if (zoomed) 1.8 else 1),
Translate.translate(0, if (zoomed) -0.9 * cY else 0)
]
content: [
Rect {
var zoomFillColor = Color.GREEN
x: bind cX - rad
y: bind cY + rad / 2
width: bind origX / 4
height: bind origX / 4
cursor: Cursor.HAND
fill: bind zoomFillColor
onMouseEntered:
function(cme:CanvasMouseEvent):Void {
zoomFillColor = Color.CYAN;
}
onMouseExited:
function(cme:CanvasMouseEvent):Void {
zoomFillColor = Color.GREEN;
}
onMouseClicked:
function(cme:CanvasMouseEvent):Void {
zoomed = not zoomed;
}
},

Как всегда, пожалуйста, оставьте комментарий, если у вас есть какие-либо вопросы по поводу этого примера.

С уважением,
Джим Уивер
JavaFX Script: динамические сценарии Java для многофункциональных интернет-приложений и приложений на стороне клиента.

Немедленная загрузка электронных книг (PDF) доступна на сайте книги Apress.