Hey I am trying to make a simple 2d scroller but I simply cannot seem to get the picture to scroll. I am using an ImagveView for the picture, and I have tried both a translatetransition and a pathtransition, but I can't get any good results? Here is my code:
public void aboutSceneAnimation() {
Rectangle2D psb = Screen.getPrimary().getVisualBounds();
Path path = new Path();
MoveTo moveTo = new MoveTo();
moveTo.setX(0.0);
path.getElements().add(moveTo);
PathTransition pt = new PathTransition();
pt.setDuration(Duration.INDEFINITE);
pt.setNode(map);
pt.setPath(path);
pt.setCycleCount(4);
pt.setAutoReverse(true);
pt.play();
}
public Scene aboutScene() {
Rectangle2D psb = Screen.getPrimary().getVisualBounds();
//Create the map
BorderPane border = new BorderPane();
border.getChildren().addAll(map2);
//Size the map
map2.setFitWidth(psb.getWidth());
map2.setFitHeight(psb.getHeight());
Scene scene = new Scene(border, 500, 500);
aboutSceneAnimation();
return scene;
}
The way it works is that when the program starts there is a start scene loaded into my stage, and then I just show the stage. When a button is pressed I simply change to the aboutScene which also calls the aboutSceneAnimation, which is where I want the map to scroll. Any ideas would be greatly appreciated!
-Cheers
You need to use a Pane instead of a BorderPane, because in a BorderPane the center node will be resized to fill the available space in the middle.
In your PathTransition you only add from where to start, i. e. the MoveTo, but you don't add where it should go, e. g. a LineTo.
Additional note:
Since your example in the question contains only bits and pieces that don't work together, please read about How to create a Minimal, Complete, and Verifiable example.
Related
I'm attempting to create something like a minimap with JavaFX, i.e. a (darkened) background image with some circles layered on top of it. Some of these circles need to be able to shed light on the background, revealing a small part of it. The following figure shows what I am aiming at.
I have worked my way forward using this SO solution, but at the moment, I am stuck because it seems that you can only set one instance of javafx.scene.effect.Lighting on the underlying StackPane.
I would really like to keep this as simple as possible and ideally only employ JavaFX. Any help is greatly appreciated :)
I recommend adding together Circles filled with a RadialGradient on a Pane with black background using BlendMode.LIGHTEN and combining this with a ImageView containing the "map" using BlendMode.MULTIPLY:
private Circle circle;
// gradient with yellow in the center and black on the border
private final static RadialGradient GRADIENT = new RadialGradient(0, 0, 0.5, 0.5, 0.5, true, CycleMethod.NO_CYCLE, new Stop(0, Color.YELLOW), new Stop(1, Color.BLACK));
private void newCircle(Pane container) {
circle = new Circle(50, GRADIENT);
circle.setBlendMode(BlendMode.LIGHTEN);
circle.setManaged(false);
container.getChildren().add(circle);
}
private void setCirclePosition(MouseEvent event) {
circle.setCenterX(event.getX());
circle.setCenterY(event.getY());
}
#Override
public void start(Stage primaryStage) {
Image image = new Image(imageURL);
ImageView imageView = new ImageView(image);
Pane mask = new Pane();
mask.setBlendMode(BlendMode.MULTIPLY);
mask.setStyle("-fx-background-color: black;");
mask.setOnMouseMoved(this::setCirclePosition); // move cricle with mouse
newCircle(mask);
// create new circle on mouse click
mask.setOnMouseClicked(evt -> {
newCircle(mask);
setCirclePosition(evt);
});
StackPane root = new StackPane(imageView, mask);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
I have a issue with my Marquee animation with JavaFX. I have a HBox with three Nodes and in the second node I have a Text node inside that I need do the Marquee transformation, but when the text goes out of the second node I need it doesn't be visible.
I'll go to set a picture to show my issue (the text is visible in the white area).
My Hbox code:
HBox bill = new HBox(0);
bill.getChildren().addAll(logoPane,product,total);
bill.setBackground(new Background(new BackgroundFill(Color.web("#FFFFFF"), CornerRadii.EMPTY, Insets.EMPTY)));
bill.setHgrow(product, Priority.ALWAYS);
Animation:
timelineAnimation = new Timeline();
final KeyValue kv = new KeyValue(productLabel.translateXProperty(), -1000);
final KeyFrame kf = new KeyFrame(Duration.millis(2000), kv);
timelineAnimation.getKeyFrames().add(kf);
And how I define my product node:
productLabel.setFont(new Font("Times New Roman",30));
product = new StackPane();
product.setMaxWidth(2000);
product.setMaxHeight(100);
product.setMinWidth(574);
product.setMinHeight(100);
product.getChildren().add(productLabel);
product.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));
product.setAlignment(productLabel, Pos.CENTER);
Hope it was enough information.
Thanks!
Simply add a Rectangle as clip for the product pane and bind it's size to the size of the pane:
Rectangle clip = new Rectangle();
product.layoutBoundsProperty().addListener((observable, oldValue, newValue) -> {
clip.setWidth(newValue.getWidth());
clip.setHeight(newValue.getHeight());
});
product.setClip(clip);
This will make sure no descendants of product are drawn outside the bounds of this node.
I am trying to create a continuous animation, eventually the goal would be a bouncing ball that bounces off the edges of the screen, however, one step at a time.
I started with the sample code from Oracle that has an animation of circles that move for 40 seconds.
public void start(Stage primaryStage)
{
Group root = new Group();
Scene scene = new Scene(root, 800, 600);
primaryStage.setScene(scene);
Group circles = new Group();
for (int i = 0; i < 1; i++)
{
MovingCircle circle = new MovingCircle(150, Color.web("white", 0.05));
circle.setStrokeType(StrokeType.OUTSIDE);
circle.setStroke(Color.web("black", 0.16));
circle.setStrokeWidth(4);
circles.getChildren().add(circle);
}
root.getChildren().add(circles);
Timeline timeline = new Timeline();
timeline.setCycleCount(Timeline.INDEFINITE);
for (Node circle: circles.getChildren())
{
if(circle instanceof MovingCircle)
{
MovingCircle c = (MovingCircle)circle;
timeline.getKeyFrames().addAll(
/* new KeyFrame(Duration.ZERO, // set start position at 0
new KeyValue(circle.translateXProperty(), random() * 800),
new KeyValue(circle.translateYProperty(), random() * 600)
),*/
new KeyFrame(new Duration(10), // set end position at 40s
c.getXMovement(), c.getYMovement())
);
c.updateCenter();
}
}
// play 40s of animation
timeline.play();
primaryStage.show();
}
I created a new MovingCircle that extends Circle to try and add other stuff to it later. The two new class methods return exactly what was commented out from the default code given.
I changed the cycle to indefinite so that it would go forever. All the circle does though is bounce between its original starting point and the translated point. I have tried updating its center location in hopes that the next bounce would move it to a different location, however, that doesn't work.
I am at quite a loss as to what to try next to get this working more the way I was hoping.
I am working on a visualization project. Based on my data I am plotting hundreds of small circle on canvas. I want to add a mouse over event so that whenever a mouse is the enclosing area of a circle it will show some node property from my data as a tool tip or as text on the canvas.
My current drawCircle method
function drawCircle(canvas,x,y,r)
{
canvas.strokeStyle = "#000000";
canvas.fillStyle = "#FFFF00";
canvas.lineWidth = 2;
canvas.beginPath();
canvas.arc(x,y,r,0,Math.PI*2,true);
canvas.stroke();
canvas.fill();
canvas.closePath();
}
I have looked into kinetic.js
But can't figure it out how I can call my drawCircle [repetitively] method using their library.
Any help will be highly appreciated.
If you still want to use KineticJS, you would put the Kinetic shape stuff inside your drawCircle routine. This is basically pulled out of their tutorial and stripped down:
function drawCircle(stage,x,y,r) {
var circle = new Kinetic.Shape(function(){
var context = this.getContext();
// draw the circle here: strokeStyle, beginPath, arc, etc...
});
circle.addEventListener("mouseover", function(){
// do something
});
stage.add(circle);
}
If you don't want to use KineticJS after all, you will need to remember for yourself the positions and radii of every circle you drew, and then do something like this:
canvas.onmouseover = function onMouseover(e) {
var mx = e.clientX - canvas.clientLeft;
var my = e.clientY - canvas.clientTop;
// for each circle...
if ((mx-cx)*(mx-cx)+(my-cy)*(my-cy) < cr*cr)
// the mouse is over that circle
}
I am working on an app in which images are flying on the Screen.
I need to implement:
Hold onto any of the flying images on Tap
Drag the image to certain position of the user's choice by letting the user hold it.
Here is another easy way to do dragging.
Just draw your image (Texture2d) with respect to a Rectangle instead of Vector2.
Your image variables should look like this
Texture2d image;
Rectangle imageRect;
Draw your image with respect to "imageRect" in Draw() method.
spriteBatch.Draw(image,imageRect,Color.White);
Now in Update() method handle your image with single touch input.
//Move your image with your logic
TouchCollection touchLocations = TouchPanel.GetState();
foreach(TouchLocation touchLocation in touchLocations)
{
Rectangle touchRect = new Rectangle
(touchLocation.Position.X,touchLocation.Position.Y,10,10);
if(touchLocation.State == TouchLocationState.Moved
&& imageRect.Intersects(touchRect))
{
imageRect.X = touchRect.X;
imageRect.Y = touchRect.Y;
}
//you can bring more beauty by bringing centre point
//of imageRect instead of initial point by adding width
//and height to X and Y respectively and divide it by 2
There's a drag-and-drag example in XNA here: http://geekswithblogs.net/mikebmcl/archive/2011/03/27/drag-and-drop-in-a-windows-xna-game.aspx
When you load your image in, you'll need a BoundingBox or Rectangle Object to control where it is.
So, in the XNA app on your phone, you should have a couple of objects declared for your texture.
Texture2D texture;
BoundingBox bBox;
Vector2 position;
bool selected;
Then after you load your image content, keep your bounding box updated with the position of your image.
bBox.Min = new Vector3(position, 1.0f);
bBox.Max = new Vector3(position.X + texture.Width, position.Y + texture.Height, 0f);
Then also in your update method, you should have a touch collection initialized to handle input from the screen, get the positions of the touch collection, loop through them and see if they intersect your boundingbox.
foreach (Vector2 pos in touchPositions)
{
BoundingBox bb = new BoundingBox();
bb.Min = new Vector3(pos, 1.0f);
bb.Max = new Vector3(pos, 0f);
if (bb.Intersects(bBox)
{
if (selected)
{
//do something
}
else
{
selected = true;
}
}
}
From there, you have whether your object is selected or not. Then just use the gestures events to determine what you want to do with your texture object.