I have a moveable group inside a Stackpane (So I can use the mouse for zooming and panning)
I am struggling with translating my group so that it moves to a given position on klick.
I am using TranslateTransition
like so:
public void goTo(double x, double y) {
TranslateTransition tt = new TranslateTransition();
tt.setNode(group);
tt.setDuration(Duration.millis(TRANSITION_TIME));
tt.setInterpolator(Interpolator.EASE_BOTH);
tt.setToX(x);
tt.setToY(y);
tt.playFromStart();
}
Look at the given picture that demonstrates the problem:
- Black is my group
- Red is the currently visible area of my group
- Green is a circle within the visible area on screen
- Purple is a circle somewhere else in the group (can be in the non-visible area)
- Light purple is the intented target for the movement of the group after clicking the green circle
So my goal is that after clicking on the green circle the purple circle (and the complete group) will move so that the purple circle is in the center of the visible area (light purple in the screenshot - This also implies that i.e the green circle will move to the non visible area)
So from my understanding the groups translateX
and translateY
position are the origin of the move. But I do not know who to determine the correct x and y distances to perform the move I also do not know how to get the boundries of the currently visible red area.
I tried something like but I think I am not sure how to use getBoundsInParent properly:
goTo(purpleCircle.getCenterX() - group.getBoundsInParent().getWidth() / 2.0, -purpleCircle.getCenterY() + group.getBoundsInParent().getHeight() / 2.0);
MWE
Question: How to move the purple circle into the middle of the screen when clicking on the green circle (no matter how far I am zoomed in on the green circle)
package com.example.sandbox;
import javafx.animation.Interpolator;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.util.concurrent.atomic.AtomicReference;
public class TranslateTest extends Application {
Group group;
@Override
public void start(Stage primaryStage) {
StackPane sp = new StackPane();
group = new Group();
sp.getChildren().add(group);
Scene primaryScene = new Scene(sp, 1024, 600);
AtomicReference<Double> scrollX = new AtomicReference<>((double) 0);
AtomicReference<Double> scrollY = new AtomicReference<>((double) 0);
// Add scrolling
sp.setOnMouseDragged(
event -> {
double newX = event.getX();
double newY = event.getY();
double diffX = newX - scrollX.get();
double diffY = newY - scrollY.get();
group.setTranslateX(group.getTranslateX() + diffX);
group.setTranslateY(group.getTranslateY() + diffY);
scrollX.set(newX);
scrollY.set(newY);
}
);
// Record mouse position for correct scrolling
sp.setOnMouseMoved(
event -> {
scrollX.set(event.getX());
scrollY.set(event.getY());
}
);
// Zooming
sp.setOnScroll(
event -> {
double oldScale = sp.getScaleX();
double newScale = oldScale + event.getDeltaY() * 0.01;
// Limit scale
newScale = Math.max(0.2, Math.min(32, newScale));
sp.setScaleX(newScale);
sp.setScaleY(newScale);
scrollX.set(event.getX());
scrollY.set(event.getY());
// Zoom to mouse cursor
group.setTranslateX(group.getTranslateX() + (scrollX.get() - sp.getWidth() / 2) * (oldScale - newScale) / newScale /* * newScale / sp.getWidth()*/);
group.setTranslateY(group.getTranslateY() + (scrollY.get() - sp.getHeight() / 2) * (oldScale - newScale) / newScale /* * newScale / sp.getHeight()*/);
}
);
primaryStage.setScene(primaryScene);
sp.setPrefWidth(1024);
sp.setPrefHeight(600);
System.out.println(group.getBoundsInParent());
// Display data
Circle purple = new Circle(-50, 0, 3);
purple.setFill(Color.PURPLE);
Circle green = new Circle(0, 0, 3);
green.setFill(Color.GREEN);
green.setOnMouseClicked(event -> {
goTo(-purple.getCenterX(), purple.getCenterY());
});
sp.setScaleX(15);
sp.setScaleY(15);
group.getChildren().add(purple);
group.getChildren().add(green);
primaryStage.show();
}
public void goTo(double x, double y) {
TranslateTransition tt = new TranslateTransition();
tt.setNode(group);
tt.setDuration(Duration.millis(2000));
tt.setInterpolator(Interpolator.EASE_BOTH);
tt.setToX(x);
tt.setToY(y);
tt.playFromStart();
}
public static void main(String[] args) {
launch();
}
}