-
-
Save skrb/49b71f2371570be55cd5 to your computer and use it in GitHub Desktop.
Drawing Song of Irof
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package irofdrawingsong; | |
import javafx.animation.KeyFrame; | |
import javafx.animation.KeyValue; | |
import javafx.animation.ParallelTransition; | |
import javafx.animation.PathTransition; | |
import javafx.animation.SequentialTransition; | |
import javafx.animation.Timeline; | |
import javafx.application.Application; | |
import javafx.beans.binding.Bindings; | |
import javafx.event.ActionEvent; | |
import javafx.event.EventHandler; | |
import javafx.scene.Group; | |
import javafx.scene.Scene; | |
import javafx.scene.control.Button; | |
import javafx.scene.input.MouseEvent; | |
import javafx.scene.layout.StackPane; | |
import javafx.scene.paint.Color; | |
import javafx.scene.shape.Arc; | |
import javafx.scene.shape.Circle; | |
import javafx.scene.shape.CubicCurve; | |
import javafx.scene.shape.Line; | |
import javafx.scene.shape.Polygon; | |
import javafx.scene.shape.Rectangle; | |
import javafx.scene.shape.StrokeLineCap; | |
import javafx.scene.text.Font; | |
import javafx.scene.text.Text; | |
import javafx.stage.Stage; | |
import javafx.util.Duration; | |
public class IrofDrawingSong extends Application { | |
private Text lyrics; | |
private Group startButton; | |
private Group container; | |
@Override | |
public void start(Stage stage) { | |
Group root = new Group(); | |
Scene scene = new Scene(root, 300, 360); | |
container = new Group(); | |
root.getChildren().add(container); | |
initStartButton(root, container); | |
lyrics = new Text(""); | |
lyrics.setLayoutX(24); | |
lyrics.setLayoutY(330); | |
lyrics.setFont(Font.font(null, 16)); | |
root.getChildren().add(lyrics); | |
stage.setTitle("Irof Drawing Song"); | |
stage.setScene(scene); | |
stage.show(); | |
} | |
private void initStartButton(Group root, final Group container) { | |
startButton = new Group(); | |
startButton.setLayoutX(50); | |
startButton.setLayoutY(50); | |
Circle circle = new Circle(100, 100, 80); | |
circle.setStrokeWidth(10.0); | |
circle.setStroke(Color.LIGHTGRAY); | |
circle.setFill(Color.WHITE); | |
startButton.getChildren().add(circle); | |
Polygon triangle = new Polygon(); | |
triangle.getPoints().addAll(new Double[]{ | |
180.0, 100.0, | |
60.0, 100 + Math.sqrt(4_800), | |
60.0, 100 - Math.sqrt(4_800) }); | |
triangle.setFill(Color.LIGHTGRAY); | |
startButton.getChildren().add(triangle); | |
startButton.setOnMousePressed(new EventHandler<MouseEvent>() { | |
@Override | |
public void handle(MouseEvent t) { | |
startAnimation(container); | |
startButton.setOpacity(0.0); | |
} | |
}); | |
root.getChildren().add(startButton); | |
} | |
private void startAnimation(final Group container) { | |
container.getChildren().clear(); | |
new Timeline( | |
new KeyFrame(Duration.ZERO, new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
drawFrameBorder(container, 4_000L); | |
lyrics.setText("これっくらいの canvas にっ"); | |
} | |
}), | |
new KeyFrame(new Duration(5_000), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
drawOutline(container, 2_000L); | |
lyrics.setText("ぐるっと輪郭ちょっと描いて\nぱっくぱっく開いたお口をつっけて"); | |
} | |
}), | |
new KeyFrame(new Duration(8_000), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
drawBalloon(container, 3_000L); | |
lyrics.setText("ふっきだっしはっベッジェきょっくせんっ"); | |
} | |
}), | |
new KeyFrame(new Duration(12_000), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
drawLeader(container, 1_500L); | |
lyrics.setText("点、点、点、点、つっぶやっいて"); | |
} | |
}), | |
new KeyFrame(new Duration(15_000), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
drawEye(container, 1_000L); | |
lyrics.setText("あーなを開ーけたらいろふさん"); | |
} | |
}), | |
new KeyFrame(new Duration(17_000), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
startButton.setOpacity(0.5); | |
} | |
}) | |
).play(); | |
} | |
private void drawFrameBorder(final Group container, final long duration) { | |
Line topBorder = new Line(0.0, 0.0, 0.0, 0.0); | |
topBorder.setStrokeWidth(5.0); | |
container.getChildren().add(topBorder); | |
final Line rightBorder = new Line(300.0, 0.0, 300.0, 0.0); | |
rightBorder.setStrokeWidth(5.0); | |
final Line bottomBorder = new Line(300.0, 300.0, 300.0, 300.0); | |
bottomBorder.setStrokeWidth(5.0); | |
final Line leftBorder = new Line(0.0, 300.0, 0.0, 300.0); | |
leftBorder.setStrokeWidth(5.0); | |
new SequentialTransition( | |
new Timeline( | |
new KeyFrame(Duration.ZERO, new KeyValue(topBorder.endXProperty(), 0.0)), | |
new KeyFrame(new Duration(duration/4), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
container.getChildren().add(rightBorder); | |
} | |
}, | |
new KeyValue(topBorder.endXProperty(), 300.0)) | |
), | |
new Timeline( | |
new KeyFrame(Duration.ZERO, new KeyValue(rightBorder.endYProperty(), 0.0)), | |
new KeyFrame(new Duration(duration/4), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
container.getChildren().add(bottomBorder); | |
} | |
}, | |
new KeyValue(rightBorder.endYProperty(), 300.0)) | |
), | |
new Timeline( | |
new KeyFrame(Duration.ZERO, new KeyValue(bottomBorder.endXProperty(), 300.0)), | |
new KeyFrame(new Duration(duration/4), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
container.getChildren().add(leftBorder); | |
} | |
}, | |
new KeyValue(bottomBorder.endXProperty(), 0.0)) | |
), | |
new Timeline( | |
new KeyFrame(Duration.ZERO, new KeyValue(leftBorder.endYProperty(), 300.0)), | |
new KeyFrame(new Duration(duration/4), new KeyValue(leftBorder.endYProperty(), 0.0)) | |
) | |
).play(); | |
} | |
private void drawOutline(final Group container, long duration) { | |
Arc arc = new Arc(242.0, 250.0, 117.0, 117.0, 188.0, 0.0); | |
arc.setClip(new Rectangle(0, 0, 300, 300)); | |
arc.setFill(null); | |
arc.setStroke(Color.BLACK); | |
arc.setStrokeWidth(10.0); | |
arc.setStrokeLineCap(StrokeLineCap.ROUND); | |
container.getChildren().add(arc); | |
final Line upperJaw = new Line(146, 184.5, 146, 184.5); | |
upperJaw.setStrokeWidth(10.0); | |
upperJaw.setStrokeLineCap(StrokeLineCap.ROUND); | |
final Line lowerJaw = new Line(210, 255, 210, 255); | |
lowerJaw.setStrokeWidth(10.0); | |
lowerJaw.setStrokeLineCap(StrokeLineCap.ROUND); | |
new SequentialTransition( | |
new Timeline( | |
new KeyFrame(Duration.ZERO, new KeyValue(arc.lengthProperty(), 0.0)), | |
new KeyFrame(new Duration(duration/2), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
container.getChildren().add(upperJaw); | |
} | |
}, | |
new KeyValue(arc.lengthProperty(), 318.0)) | |
), | |
new Timeline( | |
new KeyFrame(Duration.ZERO, new KeyValue(upperJaw.endXProperty(), 146), | |
new KeyValue(upperJaw.endYProperty(), 184.5)), | |
new KeyFrame(new Duration(duration/4), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
container.getChildren().add(lowerJaw); | |
} | |
}, | |
new KeyValue(upperJaw.endXProperty(), 210), | |
new KeyValue(upperJaw.endYProperty(), 255)) | |
), | |
new Timeline( | |
new KeyFrame(Duration.ZERO, new KeyValue(lowerJaw.endXProperty(), 210), | |
new KeyValue(lowerJaw.endYProperty(), 255)), | |
new KeyFrame(new Duration(duration/4), new KeyValue(lowerJaw.endXProperty(), 126), | |
new KeyValue(lowerJaw.endYProperty(), 266)) | |
) | |
).play(); | |
} | |
private void drawBalloon(final Group container, final long duration) { | |
Line upperLine = new Line(50.0, 30.0, 50.0, 30.0); | |
upperLine.setStrokeWidth(10.0); | |
container.getChildren().add(upperLine); | |
Arc rightArc = new Arc(153, 60, 30, 30, 90, 0); | |
rightArc.setFill(null); | |
rightArc.setStroke(Color.BLACK); | |
rightArc.setStrokeWidth(10.0); | |
container.getChildren().add(rightArc); | |
final Line bottomLine1 = new Line(153.0, 90.0, 153.0, 90.0); | |
bottomLine1.setStrokeWidth(10.0); | |
bottomLine1.setStrokeLineCap(StrokeLineCap.ROUND); | |
final CubicCurve curve1 = new CubicCurve(105, 90, 105, 90, 90, 105, 105, 90); | |
curve1.setFill(null); | |
curve1.setStroke(Color.BLACK); | |
curve1.setStrokeWidth(10.0); | |
curve1.setStrokeLineCap(StrokeLineCap.ROUND); | |
final CubicCurve curve2 = new CubicCurve(129, 141, 90, 135, 66, 120, 129, 141); | |
curve2.setFill(null); | |
curve2.setStroke(Color.BLACK); | |
curve2.setStrokeWidth(10.0); | |
curve2.setStrokeLineCap(StrokeLineCap.ROUND); | |
final CubicCurve drawPath = new CubicCurve(129, 141, 90, 135, 66, 120, 81, 90); | |
final Circle circle = new Circle(129, 141, 1); | |
curve2.endXProperty().bind(Bindings.add(circle.centerXProperty(), | |
circle.translateXProperty())); | |
curve2.endYProperty().bind(Bindings.add(circle.centerYProperty(), | |
circle.translateYProperty())); | |
final Line bottomLine2 = new Line(81.0, 90.0, 81.0, 90.0); | |
bottomLine2.setStrokeWidth(10.0); | |
bottomLine2.setStrokeLineCap(StrokeLineCap.ROUND); | |
Arc leftArc = new Arc(50, 60, 30, 30, 270, 0); | |
leftArc.setFill(null); | |
leftArc.setStroke(Color.BLACK); | |
leftArc.setStrokeWidth(10.0); | |
container.getChildren().add(leftArc); | |
PathTransition transition = new PathTransition(new Duration(300), drawPath); | |
transition.setNode(circle); | |
new SequentialTransition( | |
new Timeline( | |
new KeyFrame(Duration.ZERO, new KeyValue(upperLine.endXProperty(), 50)), | |
new KeyFrame(new Duration(duration/6), new KeyValue(upperLine.endXProperty(), 153)) | |
), | |
new Timeline( | |
new KeyFrame(Duration.ZERO, new KeyValue(rightArc.lengthProperty(), 0)), | |
new KeyFrame(new Duration(duration/6), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
container.getChildren().add(bottomLine1); | |
} | |
}, | |
new KeyValue(rightArc.lengthProperty(), -180)) | |
), | |
new Timeline( | |
new KeyFrame(Duration.ZERO, new KeyValue(bottomLine1.endXProperty(), 153)), | |
new KeyFrame(new Duration(duration/12), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
container.getChildren().add(curve1); | |
} | |
}, | |
new KeyValue(bottomLine1.endXProperty(), 105)) | |
), | |
new Timeline( | |
new KeyFrame(Duration.ZERO, new KeyValue(curve1.endXProperty(), 105), | |
new KeyValue(curve1.endYProperty(), 90)), | |
new KeyFrame(new Duration(duration/6), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
container.getChildren().add(curve2); | |
} | |
}, | |
new KeyValue(curve1.endXProperty(), 129), | |
new KeyValue(curve1.endYProperty(), 141)) | |
), | |
new ParallelTransition(transition, | |
new Timeline( | |
new KeyFrame(new Duration(0), new KeyValue(curve2.controlX1Property(), 129), | |
new KeyValue(curve2.controlY1Property(), 141), | |
new KeyValue(curve2.controlX2Property(), 129), | |
new KeyValue(curve2.controlY2Property(), 141)), | |
new KeyFrame(new Duration(duration/6), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
container.getChildren().add(bottomLine2); | |
} | |
}, | |
new KeyValue(curve2.controlX1Property(), 90), | |
new KeyValue(curve2.controlY1Property(), 135), | |
new KeyValue(curve2.controlX2Property(), 66), | |
new KeyValue(curve2.controlY2Property(), 120)))), | |
new Timeline( | |
new KeyFrame(Duration.ZERO, new KeyValue(bottomLine2.endXProperty(), 81)), | |
new KeyFrame(new Duration(duration/12), new KeyValue(bottomLine2.endXProperty(), 50)) | |
), | |
new Timeline( | |
new KeyFrame(Duration.ZERO, new KeyValue(leftArc.lengthProperty(), 0)), | |
new KeyFrame(new Duration(duration/6), new KeyValue(leftArc.lengthProperty(), -180)) | |
) | |
).play(); | |
} | |
private void drawLeader(final Group container, final long duration) { | |
final Circle leader1 = new Circle(51, 60, 5, Color.BLACK); | |
final Circle leader2 = new Circle(84, 60, 5, Color.BLACK); | |
final Circle leader3 = new Circle(120, 60, 5, Color.BLACK); | |
final Circle leader4 = new Circle(154, 60, 5, Color.BLACK); | |
new Timeline( | |
new KeyFrame(Duration.ZERO, new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
container.getChildren().add(leader1); | |
} | |
}), | |
new KeyFrame(new Duration(duration/3), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
container.getChildren().add(leader2); | |
} | |
}), | |
new KeyFrame(new Duration(duration*2/3), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
container.getChildren().add(leader3); | |
} | |
}), | |
new KeyFrame(new Duration(duration), new EventHandler<ActionEvent>() { | |
@Override | |
public void handle(ActionEvent t) { | |
container.getChildren().add(leader4); | |
} | |
}) | |
).play(); | |
} | |
private void drawEye(final Group container, long duration) { | |
Arc arc = new Arc(255.0, 204.0, 15.0, 15.0, 0.0, 0.0); | |
arc.setFill(null); | |
arc.setStroke(Color.BLACK); | |
arc.setStrokeWidth(10.0); | |
arc.setStrokeLineCap(StrokeLineCap.ROUND); | |
container.getChildren().add(arc); | |
new Timeline( | |
new KeyFrame(Duration.ZERO, new KeyValue(arc.lengthProperty(), 0.0)), | |
new KeyFrame(new Duration(duration), new KeyValue(arc.lengthProperty(), 360.0)) | |
).play(); | |
} | |
public static void main(String... args) { | |
launch(args); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment