javafx – 在已经缩放的节点上的枢轴点进行缩放
发布时间:2020-07-09 03:50:17 所属栏目:Java 来源:互联网
导读:我正在尝试使用可缩放/可绘制的画布创建应用程序. 特征: 使用鼠标滚轮放大/缩小转动点 使用鼠标左键在画布上拖动节点 用鼠标右键拖动整个画布 只要您在比例尺1开始缩放,就可以在枢轴点进行缩放.将鼠标放在网格点上并滚动鼠标滚轮.枢轴点将保持开始缩放的位置
|
我正在尝试使用可缩放/可绘制的画布创建应用程序. 特征: >使用鼠标滚轮放大/缩小转动点 只要您在比例尺1开始缩放,就可以在枢轴点进行缩放.将鼠标放在网格点上并滚动鼠标滚轮.枢轴点将保持开始缩放的位置. 问题: 当您放大时,将鼠标移动到另一点并再次放大,然后在初始鼠标位置,枢轴点移动,缩放不再发生. 例: 以下是代码: import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Scale;
import javafx.stage.Stage;
/**
* The canvas which holds all of the nodes of the application.
*/
class PannableCanvas extends Pane {
Scale scaleTransform;
public PannableCanvas() {
setPrefSize(600,600);
setStyle("-fx-background-color: lightgrey; -fx-border-color: blue;");
// add scale transform
scaleTransform = new Scale( 1.0,1.0);
getTransforms().add( scaleTransform);
// logging
addEventFilter(MouseEvent.MOUSE_PRESSED,event -> {
System.out.println(
"canvas event: " + ( ((event.getSceneX() - getBoundsInParent().getMinX()) / getScale()) + ",scale: " + getScale())
);
System.out.println( "canvas bounds: " + getBoundsInParent());
});
}
/**
* Add a grid to the canvas,send it to back
*/
public void addGrid() {
double w = getBoundsInLocal().getWidth();
double h = getBoundsInLocal().getHeight();
// add grid
Canvas grid = new Canvas(w,h);
// don't catch mouse events
grid.setMouseTransparent(true);
GraphicsContext gc = grid.getGraphicsContext2D();
gc.setStroke(Color.GRAY);
gc.setLineWidth(1);
// draw grid lines
double offset = 50;
for( double i=offset; i < w; i+=offset) {
// vertical
gc.strokeLine( i,i,h);
// horizontal
gc.strokeLine( 0,w,i);
}
getChildren().add( grid);
grid.toBack();
}
public Scale getScaleTransform() {
return scaleTransform;
}
public double getScale() {
return scaleTransform.getY();
}
/**
* Set x/y scale
* @param scale
*/
public void setScale( double scale) {
scaleTransform.setX(scale);
scaleTransform.setY(scale);
}
/**
* Set x/y pivot points
* @param x
* @param y
*/
public void setPivot( double x,double y) {
scaleTransform.setPivotX(x);
scaleTransform.setPivotY(y);
}
}
/**
* Mouse drag context used for scene and nodes.
*/
class DragContext {
double mouseAnchorX;
double mouseAnchorY;
double translateAnchorX;
double translateAnchorY;
}
/**
* Listeners for making the nodes draggable via left mouse button. Considers if parent is zoomed.
*/
class NodeGestures {
private DragContext nodeDragContext = new DragContext();
PannableCanvas canvas;
public NodeGestures( PannableCanvas canvas) {
this.canvas = canvas;
}
public EventHandler<MouseEvent> getOnMousePressedEventHandler() {
return onMousePressedEventHandler;
}
public EventHandler<MouseEvent> getOnMouseDraggedEventHandler() {
return onMouseDraggedEventHandler;
}
private EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
// left mouse button => dragging
if( !event.isPrimaryButtonDown())
return;
nodeDragContext.mouseAnchorX = event.getSceneX();
nodeDragContext.mouseAnchorY = event.getSceneY();
Node node = (Node) event.getSource();
nodeDragContext.translateAnchorX = node.getTranslateX();
nodeDragContext.translateAnchorY = node.getTranslateY();
}
};
private EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
// left mouse button => dragging
if( !event.isPrimaryButtonDown())
return;
double scale = canvas.getScale();
Node node = (Node) event.getSource();
node.setTranslateX(nodeDragContext.translateAnchorX + (( event.getSceneX() - nodeDragContext.mouseAnchorX) / scale));
node.setTranslateY(nodeDragContext.translateAnchorY + (( event.getSceneY() - nodeDragContext.mouseAnchorY) / scale));
event.consume();
}
};
}
/**
* Listeners for making the scene's canvas draggable and zoomable
*/
class SceneGestures {
private static final double MAX_SCALE = 10.0d;
private static final double MIN_SCALE = .1d;
private DragContext sceneDragContext = new DragContext();
PannableCanvas canvas;
public SceneGestures( PannableCanvas canvas) {
this.canvas = canvas;
}
public EventHandler<MouseEvent> getOnMousePressedEventHandler() {
return onMousePressedEventHandler;
}
public EventHandler<MouseEvent> getOnMouseDraggedEventHandler() {
return onMouseDraggedEventHandler;
}
public EventHandler<ScrollEvent> getOnScrollEventHandler() {
return onScrollEventHandler;
}
private EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
// right mouse button => panning
if( !event.isSecondaryButtonDown())
return;
sceneDragContext.mouseAnchorX = event.getSceneX();
sceneDragContext.mouseAnchorY = event.getSceneY();
sceneDragContext.translateAnchorX = canvas.getTranslateX();
sceneDragContext.translateAnchorY = canvas.getTranslateY();
}
};
private EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
// right mouse button => panning
if( !event.isSecondaryButtonDown())
return;
canvas.setTranslateX(sceneDragContext.translateAnchorX + event.getSceneX() - sceneDragContext.mouseAnchorX);
canvas.setTranslateY(sceneDragContext.translateAnchorY + event.getSceneY() - sceneDragContext.mouseAnchorY);
event.consume();
}
};
/**
* Mouse wheel handler: zoom to pivot point
*/
private EventHandler<ScrollEvent> onScrollEventHandler = new EventHandler<ScrollEvent>() {
@Override
public void handle(ScrollEvent event) {
double delta = 1;
double scale = canvas.getScale(); // currently we only use Y,same value is used for X
double oldScale = scale;
if (event.getDeltaY() < 0)
scale -= delta;
else
scale += delta;
if (scale <= MIN_SCALE) {
scale = MIN_SCALE;
} else if (scale >= MAX_SCALE) {
scale = MAX_SCALE;
}
// pivot value must be untransformed,i. e. without scaling
canvas.setPivot(
((event.getSceneX() - canvas.getBoundsInParent().getMinX()) / oldScale),((event.getSceneY() - canvas.getBoundsInParent().getMinY()) / oldScale)
);
canvas.setScale( scale);
System.out.println( "new pivot x: " + canvas.scaleTransform.getPivotX() + "/" + canvas.scaleTransform.getPivotY() + ",new scale: " + scale);
System.out.println( "bounds: " + canvas.getBoundsInParent());
event.consume();
}
};
}
/**
* An application with a zoomable and pannable canvas.
*/
public class ScrollApplication extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
Group group = new Group();
// create canvas
PannableCanvas canvas = new PannableCanvas();
// we don't want the canvas on the top/left in this example => just
// translate it a bit
canvas.setTranslateX(100);
canvas.setTranslateY(100);
// create sample nodes which can be dragged
NodeGestures nodeGestures = new NodeGestures( canvas);
Label label1 = new Label("Draggable node 1");
label1.setTranslateX(10);
label1.setTranslateY(10);
label1.addEventFilter( MouseEvent.MOUSE_PRESSED,nodeGestures.getOnMousePressedEventHandler());
label1.addEventFilter( MouseEvent.MOUSE_DRAGGED,nodeGestures.getOnMouseDraggedEventHandler());
Label label2 = new Label("Draggable node 2");
label2.setTranslateX(100);
label2.setTranslateY(100);
label2.addEventFilter( MouseEvent.MOUSE_PRESSED,nodeGestures.getOnMousePressedEventHandler());
label2.addEventFilter( MouseEvent.MOUSE_DRAGGED,nodeGestures.getOnMouseDraggedEventHandler());
Label label3 = new Label("Draggable node 3");
label3.setTranslateX(200);
label3.setTranslateY(200);
label3.addEventFilter( MouseEvent.MOUSE_PRESSED,nodeGestures.getOnMousePressedEventHandler());
label3.addEventFilter( MouseEvent.MOUSE_DRAGGED,nodeGestures.getOnMouseDraggedEventHandler());
Circle circle1 = new Circle( 300,300,50);
circle1.setStroke(Color.ORANGE);
circle1.setFill(Color.ORANGE.deriveColor(1,1,0.5));
circle1.addEventFilter( MouseEvent.MOUSE_PRESSED,nodeGestures.getOnMousePressedEventHandler());
circle1.addEventFilter( MouseEvent.MOUSE_DRAGGED,nodeGestures.getOnMouseDraggedEventHandler());
Rectangle rect1 = new Rectangle(100,100);
rect1.setTranslateX(450);
rect1.setTranslateY(450);
rect1.setStroke(Color.BLUE);
rect1.setFill(Color.BLUE.deriveColor(1,0.5));
rect1.addEventFilter( MouseEvent.MOUSE_PRESSED,nodeGestures.getOnMousePressedEventHandler());
rect1.addEventFilter( MouseEvent.MOUSE_DRAGGED,nodeGestures.getOnMouseDraggedEventHandler());
canvas.getChildren().addAll(label1,label2,label3,circle1,rect1);
group.getChildren().add(canvas);
// create scene which can be dragged and zoomed
Scene scene = new Scene(group,1024,768);
SceneGestures sceneGestures = new SceneGestures(canvas);
scene.addEventFilter( MouseEvent.MOUSE_PRESSED,sceneGestures.getOnMousePressedEventHandler());
scene.addEventFilter( MouseEvent.MOUSE_DRAGGED,sceneGestures.getOnMouseDraggedEventHandler());
scene.addEventFilter( ScrollEvent.ANY,sceneGestures.getOnScrollEventHandler());
stage.setScene(scene);
stage.show();
canvas.addGrid();
}
}
显然,枢轴点计算有问题,但我无法弄清楚它是什么,以及如何解决它. (编辑:鄂州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
