我已经从 圈子 和 行 构建了以下“系统”。
<登记/>
我正试图在系统中实现两个转换。
我试图实施它但遇到问题
单独完成时,两种过渡都很好
即,当应用程序启动时,您尝试拖动绿色圆圈,整个系统完全围绕红色圆圈旋转。
同样,在启动时,拖动红色圆圈时,一切都被拖得很好。
的但
当这些拖曳中的任何一个在另一个之后被尝试时,形状会彼此远离!
请指出可能导致此行为的原因。
欢迎任何其他实现转换的方式,因为我还是JavaFx中的Animations的新手,显然不是解决问题的最佳代码。
以下是我的代码:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
public class SpindleAndWheel extends Application
{
Circle circle;
Circle oppositeCircle;
Circle pivot;
Line spindle;
Rotate rotateCircle, rotateOppositeCircle;
Translate translateCircle, translateOppositeCircle;
Translate translateCircleBack, translateOppositeCircleBack;
Translate dragTranslateCircle, dragTranslatePivot, dragTranslateOppositeCircle, dragTranslateSpindle;
double dragInitX, dragInitY;
double dragInitTheta;
double theta1,theta2;
double angleOfRotation;
double dragPivotInitX,dragPivotInitY,systemDragOffsetX,systemDragOffsetY;
double dragTranslateCircleBackupX,dragTranslatePivotBackupX, dragTranslateOppositeCircleBackupX, dragTranslateSpindleBackupX;
double dragTranslateCircleBackupY,dragTranslatePivotBackupY, dragTranslateOppositeCircleBackupY, dragTranslateSpindleBackupY;
@Override
public void start(Stage primaryStage) throws Exception
{
Stage stage = new Stage();
stage.setMinHeight(500);
stage.setMinWidth(500);
Pane root = new Pane();
circle = new Circle(150, 150, 30);
oppositeCircle = new Circle(350, 350, 30);
pivot = new Circle(250, 250, 5);
spindle = new Line(150, 150, 350, 350);
/**************** Initializing Shapes **********/
circle.setFill(Color.GREEN.deriveColor(1, 1, 1, 0.35));
circle.setStroke(Color.GREEN);
oppositeCircle.setFill(Color.BLUE.deriveColor(1, 1, 1, 0.35));
oppositeCircle.setStroke(Color.BLUE);
pivot.setFill(Color.RED.deriveColor(1, 1, 1, 0.35));
pivot.setStroke(Color.RED);
spindle.setStrokeWidth(3);
spindle.setStroke(Color.BLACK.deriveColor(1, 1, 1, 0.35));
/****************************************************/
/**************** Initializing Animations **********/
rotateCircle = new Rotate(0, 0, 0);
translateCircle = new Translate(0, 0);
translateCircleBack = new Translate(0, 0);
dragTranslateCircle = new Translate(0, 0);
rotateOppositeCircle = new Rotate(0, 0, 0);
translateOppositeCircle = new Translate(0, 0);
translateOppositeCircleBack = new Translate(0, 0);
dragTranslateOppositeCircle = new Translate(0, 0);
dragTranslatePivot = new Translate(0, 0);
dragTranslateSpindle = new Translate(0, 0);
/****************************************************/
/**************** Adding Animations **************/
circle.getTransforms().addAll(translateCircle, rotateCircle, translateCircleBack, dragTranslateCircle);
oppositeCircle.getTransforms().addAll(translateOppositeCircle, rotateOppositeCircle, translateOppositeCircleBack, dragTranslateOppositeCircle);
pivot.getTransforms().addAll(dragTranslatePivot);
spindle.getTransforms().addAll(dragTranslateSpindle);
/****************************************************/
Scene scene = new Scene(root);
stage.setScene(scene);
root.getChildren().addAll(circle,oppositeCircle,pivot,spindle);
stage.show();
/** Get angle of point of click with
* point of rotation, before drag begins **/
circle.setOnMousePressed(event -> {
dragInitX = event.getSceneX();
dragInitY = event.getSceneY();
dragInitTheta = angleOfRotation + dragInitTheta;
double initialSlope;
double pointOfRotationX,pointOfRotationY;
pointOfRotationY = pivot.getCenterY() + dragTranslatePivot.getY();
pointOfRotationX = pivot.getCenterX() + dragTranslatePivot.getX();
initialSlope = Math.atan((dragInitY - (pointOfRotationX)) / (dragInitX - (pointOfRotationY)));
theta1 = Math.toDegrees(initialSlope);
if (dragInitX < pointOfRotationX)
theta1 = (360 + theta1) % 360;
else
theta1 = 180 + theta1;
});
/********************************************/
/** Get angle of point of drags with
* point of rotation, when the drag is on **/
circle.setOnMouseDragged(event -> {
double finalSlope;
double pointOfRotationX,pointOfRotationY;
pointOfRotationY = pivot.getCenterY() + dragTranslatePivot.getY();
pointOfRotationX = pivot.getCenterX() + dragTranslatePivot.getX();
finalSlope = Math.atan((event.getSceneY() - (pointOfRotationX)) / (event.getSceneX() - (pointOfRotationY)));
theta2 = Math.toDegrees(finalSlope);
if (event.getSceneX() < pointOfRotationX)
theta2 = (360 + theta2) % 360;
else
theta2 = 180 + theta2;
angleOfRotation = theta2 - theta1;
translateCircle.setX(pointOfRotationX);
translateCircle.setY(pointOfRotationY);
rotateCircle.setAngle(angleOfRotation + dragInitTheta);
translateCircleBack.setX(-pointOfRotationX);
translateCircleBack.setY(-pointOfRotationY);
translateOppositeCircle.setX(pointOfRotationX);
translateOppositeCircle.setY(pointOfRotationY);
rotateOppositeCircle.setAngle(angleOfRotation + dragInitTheta);
translateOppositeCircleBack.setX(-pointOfRotationX);
translateOppositeCircleBack.setY(-pointOfRotationY);
spindle.setRotate(angleOfRotation + dragInitTheta);
});
/********************************************/
/** Relocate the whole system when the point of
* rotation is dragged **/
pivot.setOnMousePressed(event -> {
dragPivotInitX = event.getSceneX();
dragPivotInitY = event.getSceneY();
dragTranslateCircleBackupX = dragTranslateCircle.getX();
dragTranslateCircleBackupY = dragTranslateCircle.getY();
dragTranslatePivotBackupX = dragTranslatePivot.getX();
dragTranslatePivotBackupY = dragTranslatePivot.getY();
dragTranslateOppositeCircleBackupX = dragTranslateOppositeCircle.getX();
dragTranslateOppositeCircleBackupY = dragTranslateOppositeCircle.getY();
dragTranslateSpindleBackupX = dragTranslateSpindle.getX();
dragTranslateSpindleBackupY = dragTranslateSpindle.getY();
});
pivot.setOnMouseDragged(event -> {
systemDragOffsetX = event.getSceneX() - dragPivotInitX;
systemDragOffsetY = event.getSceneY() - dragPivotInitY;
dragTranslateCircle.setX(dragTranslateCircleBackupX + systemDragOffsetX);
dragTranslateCircle.setY(dragTranslateCircleBackupY + systemDragOffsetY);
dragTranslatePivot.setX(dragTranslatePivotBackupX+ systemDragOffsetX);
dragTranslatePivot.setY(dragTranslatePivotBackupY+ systemDragOffsetY);
dragTranslateOppositeCircle.setX(dragTranslateOppositeCircleBackupX+ systemDragOffsetX);
dragTranslateOppositeCircle.setY(dragTranslateOppositeCircleBackupY+ systemDragOffsetY);
dragTranslateSpindle.setX(dragTranslateSpindleBackupX+ systemDragOffsetX);
dragTranslateSpindle.setY(dragTranslateSpindleBackupY + systemDragOffsetY);
});
/********************************************/
}
public static void main(String[] args)
{
launch(args);
}
}
答案 0 :(得分:2)
很好的方法,但正如您已经发现的那样,它有一个主要缺点:应用一次转换后,另一种转换效果不佳。原因在于您定义转换的方式。此外,分配如此多的转换会导致复杂的系统,难以保留。
我的建议要简单得多:只需将所有形状包裹在一个Group
中,然后转换此组,在拖动轴时将其平移,或在拖动圆圈时将其旋转到轴上。请注意,您可以在此处使用setPivotX()
和setPivotY()
来指示实际的旋转点。
正如您所看到的,您只需要进行两次转换,更重要的是,您不会有任何副作用,无论是否以任何顺序应用它们。
修改强>
正如OP正确指出的那样,旋转计算中存在错误。为了完整起见,我编辑了我的答案以显示正确的代码。
private Circle circle;
private Circle oppositeCircle;
private Circle pivot;
private Line spindle;
private Group group;
private Rotate rotateGroup;
double dragInitTheta;
double theta1,theta2;
double angleOfRotation;
private Translate translateGroup;
private double dragTranslateGroupBackupX, dragTranslateGroupBackupY;
private double dragPivotInitX,dragPivotInitY,systemDragOffsetX,systemDragOffsetY;
@Override
public void start(Stage stage){
circle = new Circle(150, 150, 30);
oppositeCircle = new Circle(350, 350, 30);
pivot = new Circle(250, 250, 5);
spindle = new Line(150, 150, 350, 350);
group = new Group(circle,oppositeCircle,pivot,spindle);
/**************** Initializing Shapes **********/
circle.setFill(Color.GREEN.deriveColor(1, 1, 1, 0.35));
circle.setStroke(Color.GREEN);
oppositeCircle.setFill(Color.BLUE.deriveColor(1, 1, 1, 0.35));
oppositeCircle.setStroke(Color.BLUE);
pivot.setFill(Color.RED.deriveColor(1, 1, 1, 0.35));
pivot.setStroke(Color.RED);
spindle.setStrokeWidth(3);
spindle.setStroke(Color.BLACK.deriveColor(1, 1, 1, 0.35));
/****************************************************/
/**************** Initializing Transforms **********/
rotateGroup = new Rotate(0, 0, 0);
translateGroup = new Translate(0, 0);
/****************************************************/
/**************** Adding Transforms **************/
group.getTransforms().addAll(translateGroup,rotateGroup);
/****************************************************/
Pane root = new Pane(group);
Scene scene = new Scene(root,500,500);
stage.setScene(scene);
stage.show();
/** Get angle of point of click with
* point of rotation, before drag begins **/
circle.setOnMousePressed(event -> {
dragInitTheta = angleOfRotation + dragInitTheta;
double pointOfRotationX = pivot.getCenterX() + translateGroup.getX();
double pointOfRotationY = pivot.getCenterY() + translateGroup.getY();
double initialSlope = Math.atan((event.getSceneY() - pointOfRotationY) / (event.getSceneX() - pointOfRotationX));
theta1 = Math.toDegrees(initialSlope);
if (event.getSceneX() < pointOfRotationX)
theta1 = (360 + theta1) % 360;
else
theta1 = 180 + theta1;
});
/********************************************/
/** Get angle of point of drags with
* point of rotation, when the drag is on **/
circle.setOnMouseDragged(event -> {
double pointOfRotationX = pivot.getCenterX() + translateGroup.getX();
double pointOfRotationY = pivot.getCenterY() + translateGroup.getY();
double finalSlope = Math.atan((event.getSceneY() - pointOfRotationY) / (event.getSceneX() - pointOfRotationX));
theta2 = Math.toDegrees(finalSlope);
if (event.getSceneX() < pointOfRotationX)
theta2 = (360 + theta2) % 360;
else
theta2 = 180 + theta2;
angleOfRotation = theta2 - theta1;
rotateGroup.setPivotX(pivot.getCenterX());
rotateGroup.setPivotY(pivot.getCenterY());
rotateGroup.setAngle(angleOfRotation + dragInitTheta);
});
/********************************************/
/** Relocate the whole system when the point of
* rotation is dragged **/
pivot.setOnMousePressed(event -> {
dragPivotInitX = event.getSceneX();
dragPivotInitY = event.getSceneY();
dragTranslateGroupBackupX = translateGroup.getX();
dragTranslateGroupBackupY = translateGroup.getY();
});
pivot.setOnMouseDragged(event -> {
systemDragOffsetX = event.getSceneX() - dragPivotInitX;
systemDragOffsetY = event.getSceneY() - dragPivotInitY;
translateGroup.setX(dragTranslateGroupBackupX + systemDragOffsetX);
translateGroup.setY(dragTranslateGroupBackupY + systemDragOffsetY);
});
/********************************************/
}
答案 1 :(得分:1)
José Pereda, 精彩答案!! 更好的方法。
了解很多新东西。
只需要做一个简单的修正。
在计算阻力点的斜率时,还需要考虑(pivot)中(translateGroup.getY(),translateGroup.getX())的偏移量。 .getCenterY(),pivot.getCenterX())强>
以下是José的代码,其中包含上述更正。
PXOR