简体   繁体   English

JavaFX drawImage 旋转

[英]JavaFX drawImage rotated

I am playing with JavaFX and in the class start(Stage theStage) I have the following code:我正在使用 JavaFX,在类 start(Stage theStage) 中,我有以下代码:

/*... Scene, stage, canvas ...*/
GraphicsContext gc = canvas.getGraphicsContext2D();
Image imgage = new Image("gfx/image.png");
gc.drawImage(image, 256, 256);

How I draw it rotated without rotating the axis?我如何绘制它旋转而不旋转轴? I've found and tried this:我发现并尝试了这个:

gc.save(); // saves the current state on stack, including the current transform
gc.rotate(45);
gc.drawImage(image);
gc.restore();

However it also transforms the axis and when I move image using changing position x & y .. it goes wrong, because it makes axis rotate too.然而,它也会改变轴,当我使用改变位置 x & y 移动图像时,它会出错,因为它也会使轴旋转。 I've been thinking about recalculating movement using sin and cos functions, but I am sure there is such an easier solution.我一直在考虑使用 sin 和 cos 函数重新计算运动,但我相信有一个更简单的解决方案。

It may works with BufferedImage, but they draws it by using different Graphics class and I dont know how to make it work together.它可能适用于 BufferedImage,但他们使用不同的 Graphics 类绘制它,我不知道如何使其协同工作。

EDIT: okey, how to rotate Image only without roatiting the whole GraphicsContext?编辑:好的,如何只旋转图像而不旋转整个 GraphicsContext?

SOLVED: Thanks all for a help :)) I have solved it by using this >>已解决:感谢大家的帮助 :)) 我已经用这个解决了 >>

ImageView iv = new ImageView(new Image( "gfx/earth.png"));
iv.setRotate(40);
SnapshotParameters params = new SnapshotParameters();
params.setFill(Color.TRANSPARENT);
Image rotatedImage = iv.snapshot(params, null);
gc.drawImage(rotatedImage, 0, 0);

Let's see if I was able to understand your question...让我们看看我是否能够理解你的问题......

how to rotate Image only without rotating the whole GraphicsContext?如何仅旋转图像而不旋转整个 GraphicsContext?

You can't do that using just a GraphicsContext.您不能仅使用 GraphicsContext 来做到这一点。 You need to rotate the GraphicsContext to get a rotated image rendered onto it using the drawImage API.您需要旋转 GraphicsContext 以使用 drawImage API 将旋转的图像渲染到其上。 To prevent the rotation operation impacting other Canvas drawing operations, you can save and restore the GraphicsContext before and after performing the rotation (as it appears you are already doing from the code in your question).为防止旋转操作影响其他 Canvas 绘图操作,您可以在执行旋转之前和之后保存和恢复 GraphicsContext(因为您似乎已经在问题中的代码中这样做了)。

However, one way to accomplish what you wish without rotating the GraphicsContext is to use a SceneGraph in combination with a Canvas.但是,在不旋转 GraphicsContext 的情况下完成您希望的一种方法是将 SceneGraph 与 Canvas 结合使用。 Place the Image in a ImageView, apply a rotate transform to the image, snapshot it to get a rotated image, then draw the rotated image into your Canvas.将图像放在 ImageView 中,对图像应用旋转变换,对其进行快照以获得旋转图像,然后将旋转图像绘制到画布中。

ImageView iv = new ImageView(image);
iv.setRotate(40);
SnapshotParameters params = new SnapshotParameters();
params.setFill(Color.TRANSPARENT);
Image rotatedImage = iv.snapshot(params, null);
gc.drawImage(rotatedImage, 0, 0);

Sample code:示例代码:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.canvas.*;
import javafx.scene.image.*;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

/** Rotates and places it in a canvas */
public class RotatedImageInCanvas extends Application {
    @Override public void start(Stage stage) {
        Image image = new Image(
            "http://worldpress.org/images/maps/world_600w.jpg", 350, 0, true, true
        );

        // creates a canvas on which rotated images are rendered.
        Canvas canvas = new Canvas(600, 400);
        GraphicsContext gc = canvas.getGraphicsContext2D();

        ImageView iv = new ImageView(image);
        iv.setRotate(40);
        SnapshotParameters params = new SnapshotParameters();
        params.setFill(Color.TRANSPARENT);
        Image rotatedImage = iv.snapshot(params, null);
        gc.drawImage(rotatedImage, 0, 0);

        // supplies a tiled background image on which the canvas is drawn.
        StackPane stack = new StackPane();
        stack.setMaxSize(canvas.getWidth(), canvas.getHeight());
        stack.setStyle("-fx-background-image: url('http://1.bp.blogspot.com/_wV5JMD1OISg/TDYTYxuxR4I/AAAAAAAAvSo/a0zT8nwPV8U/s400/louis-vuitton-nice-beautiful.jpg');");
        stack.getChildren().add(
                canvas
        );

        // places a resizable padded frame around the canvas.
        StackPane frame = new StackPane();
        frame.setPadding(new Insets(20));
        frame.getChildren().add(stack);

        stage.setScene(new Scene(frame, Color.BURLYWOOD));
        stage.show();
    }

    public static void main(String[] args) { launch(RotatedImageInCanvas.class); }
}

Normally, I would not recommend mixing scene graph and canvas APIs as done in the above sample, but instead just code to only the scene graph API or only the canvas API.通常,我不建议像在上面的示例中那样混合使用场景图和画布 API,而是只对场景图 API 或仅对画布 API 进行编码。

For a sample of a canvas only solution, see the answer to:有关仅画布解决方案的示例,请参阅以下答案:

In general, for most operations, I find working with the Scene Graph API simpler than coding to the Canvas API and recommend using the Scene Graph API rather than the Canvas API for most tasks.一般来说,对于大多数操作,我发现使用 Scene Graph API 比编码到 Canvas API 更简单,并且建议在大多数任务中使用 Scene Graph API 而不是 Canvas API。

According to the other comment you should add setViewport and setTransform like I did in my rotateImage function if you want to rotate the image around a point and don't want to change the center of the image.根据其他评论,如果您想围绕一个点旋转图像并且不想更改图像的中心,您应该像我在 rotateImage 函数中所做的那样添加 setViewport 和 setTransform 。

public Image rotateImage(Image image, int rotation) {
    ImageView iv = new ImageView(image);
    SnapshotParameters params = new SnapshotParameters();
    params.setFill(Color.TRANSPARENT);
    params.setTransform(new Rotate(rotation, image.getHeight() / 2, image.getWidth() / 2));
    params.setViewport(new Rectangle2D(0, 0, image.getHeight(), image.getWidth()));
    return iv.snapshot(params, null);
}

A rather quick-and-dirty method that also works is to translate and rotate the entire GraphicsContext and then draw the image relative to 0 (in this case, the rotation is from the middle of the image).一个相当快速和肮脏的方法也有效是平移和旋转整个 GraphicsContext,然后相对于 0 绘制图像(在这种情况下,旋转是从图像的中间开始)。 Then, after the image is drawn, reverse the action.然后,在绘制图像后,反转动作。

For example, if you have an image (img), a GraphicsContext (gc) and a position for the image (xp, yp), then:例如,如果您有一个图像 (img)、一个 GraphicsContext (gc) 和图像的位置 (xp, yp),则:

// Translate and rotate.
gc.translate(xp, yp);
gc.rotate(degrees);

// Note how the image is drawn relative to 0.  Since the image needs to be
// rotated around the image center, the center is simply half of the image
// dimension.
gc.drawImage( image, -image.getWidth/2.0, -image.getImageHeight/2.0);

// Reverse the translation and rotation once drawn.
gc.rotate(-degrees);
gc.translate(-xp, -yp);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM