我想在画布上旋转绘制图像。使用drawImage(image, 0, 0)
我可以绘制图像但是如何旋转该图像,例如45度并绘制它,然后在同一画布上的前一图像之后以-50度旋转绘制其他图像?
graphicContext2D
对我不起作用,因为它会旋转所有画布内容。
那我怎么能这样做呢?
答案 0 :(得分:16)
以下是一个示例,遵循与Katona的答案类似的原则,唯一的区别是它通过应用自定义变换旋转任意轴点的图像。
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.canvas.*;
import javafx.scene.image.Image;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
/** Rotates images round pivot points and places them in a canvas */
public class RotatedImageInCanvas extends Application {
/**
* Sets the transform for the GraphicsContext to rotate around a pivot point.
*
* @param gc the graphics context the transform to applied to.
* @param angle the angle of rotation.
* @param px the x pivot co-ordinate for the rotation (in canvas co-ordinates).
* @param py the y pivot co-ordinate for the rotation (in canvas co-ordinates).
*/
private void rotate(GraphicsContext gc, double angle, double px, double py) {
Rotate r = new Rotate(angle, px, py);
gc.setTransform(r.getMxx(), r.getMyx(), r.getMxy(), r.getMyy(), r.getTx(), r.getTy());
}
/**
* Draws an image on a graphics context.
*
* The image is drawn at (tlpx, tlpy) rotated by angle pivoted around the point:
* (tlpx + image.getWidth() / 2, tlpy + image.getHeight() / 2)
*
* @param gc the graphics context the image is to be drawn on.
* @param angle the angle of rotation.
* @param tlpx the top left x co-ordinate where the image will be plotted (in canvas co-ordinates).
* @param tlpy the top left y co-ordinate where the image will be plotted (in canvas co-ordinates).
*/
private void drawRotatedImage(GraphicsContext gc, Image image, double angle, double tlpx, double tlpy) {
gc.save(); // saves the current state on stack, including the current transform
rotate(gc, angle, tlpx + image.getWidth() / 2, tlpy + image.getHeight() / 2);
gc.drawImage(image, tlpx, tlpy);
gc.restore(); // back to original state (before rotation)
}
@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();
drawRotatedImage(gc, image, 40, 0, 0);
drawRotatedImage(gc, image, -50, 400, 200);
// 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); }
}
答案 1 :(得分:3)
好吧,我从来没有使用过JavaFX,但是浏览它的API文档,我想出了这个解决方案(我实际上没有尝试过,所以它可能是错的):
Canvas canvas = ...
Image img = ...
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.save(); // saves the current state on stack, including the current transform
gc.rotate(45);
gc.drawImage(img);
gc.restore(); // back to original state (before rotation)
gc.save();
gc.rotate(-50);
gc.drawImage(img);
gc.restore();
我不知道它是否在这里工作,但是这个想法(转换堆栈)是借鉴其他绘图API(如OpenGL)。
答案 2 :(得分:2)
上述问题也可以通过创建不同的画布层来解决。
private void createLayers(){
// Layers 1&2 are the same size
layer1 = new Canvas(300,250);
layer2 = new Canvas(300,250);
// Obtain Graphics Contexts
gc1 = layer1.getGraphicsContext2D();
gc1.setFill(Color.GREEN);
gc1.fillOval(50,50,20,20);
gc1.getCanvas().setRotate(45);
gc2 = layer2.getGraphicsContext2D();
gc2.setFill(Color.BLUE);
gc2.fillOval(100,100,20,20);
gc.getCanvas().setRotate(135);
}
...
private void addLayers(){
// Add Layers
borderPane.setTop(cb);
Pane pane = new Pane();
pane.getChildren().add(layer1);
pane.getChildren().add(layer2);
layer1.toFront();
borderPane.setCenter(pane);
root.getChildren().add(borderPane);
}
答案 3 :(得分:0)
在旋转和缩放图像后,父容器的布局管理器未正确调整其大小,在ImageViews中也遇到了类似的问题。
根据此处提出的想法,我创建了一个ImageCanvas,可以反映渲染图像的尺寸,无论旋转还是缩放。
请参见https://github.com/treimers/JfxImageCanvas
享受 托尔斯滕