0

I have a question that as per object concerns the Canvas and its GraphiContext.

In the following code I have reported a JavaFX Application that has the Canvas as its main object.

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class canvasSVG extends Application{

    private Double angle = 0.0;

    @Override
    public void start(Stage stage) {
        Canvas canvas = new Canvas(500, 500);
        GraphicsContext gc = canvas.getGraphicsContext2D();

        gc.setFill(Color.GREEN);
        gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());

        String svgPath = "m 0 10 v -24 M 0 -14 L 8 -16 M -2 10 h 4 l -2 5 l -2 -5";

        canvas.setOnMousePressed(e->{
            if(e.getButton()==MouseButton.PRIMARY) {
                System.out.println("PUT: "+ angle);

                gc.save();
                gc.setStroke(Color.BLUE);
                gc.translate(250,250);
                gc.rotate(angle);                           
                gc.scale(10, 10);

                gc.appendSVGPath(svgPath);
                gc.stroke();

                angle = angle+50;                                               
                gc.restore();           
            }

        });

        canvas.setOnMouseClicked(e->{
            if(e.getButton()==MouseButton.SECONDARY) {
                System.out.println("CLEAN "+ angle);

                gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
                gc.setFill(Color.GREEN);
                gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
            }
        });

        StackPane pane = new StackPane(canvas);

        Scene scene = new Scene(pane);
        stage.setTitle("Canvas Demo");
        stage.setScene(scene);
        stage.sizeToScene();
        stage.centerOnScreen();
        stage.show();
    }

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

On clicking with the left mouse button I add the SVG path to the canvas and on clicking with the right mouse button I remove it from the canvas.

The problem is that once the rotation has happened the first time, the angle of the geometric figure in the canvas doesn't change.

1 Answers1

0

The method appendSVGPath() specifies: "The coordinates are transformed by the current transform as they are added to the path and unaffected by subsequent changes to the transform." As an alternative, rotate the enclosing Canvas as shown below. Also consider this alternate approach to scaling SVGPath.

image

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

/** @see https://stackoverflow.com/a/70945900/230513 */
public class CanvasSVG extends Application {

    private static final double DIM = 400;
    private static final Color BG = Color.GREEN;
    private final Canvas canvas = new Canvas(DIM, DIM);
    private final GraphicsContext gc = canvas.getGraphicsContext2D();
    private Double angle = 0.0;

    @Override
    public void start(Stage stage) {
        clear();
        draw();
        canvas.setOnMousePressed(e -> {
            if (e.getButton() == MouseButton.PRIMARY) {
                draw();
                angle += 50;
                canvas.setRotate(angle);
            } else if (e.getButton() == MouseButton.SECONDARY) {
                clear();
                angle = 50.0;
            }
        });

        StackPane pane = new StackPane(canvas);
        pane.setBackground(new Background(new BackgroundFill(
            BG, CornerRadii.EMPTY, Insets.EMPTY)));
        Scene scene = new Scene(pane);
        stage.setTitle("Canvas Demo");
        stage.setScene(scene);
        stage.centerOnScreen();
        stage.show();
    }

    private void draw() {
        String svgPath = "m 0 10 v -24 M 0 -14 L 8 -16 M -2 10 h 4 l -2 5 l -2 -5";
        gc.save();
        gc.setStroke(Color.BLUE);
        gc.translate(DIM / 2, DIM / 2);
        gc.scale(10, 10);
        gc.appendSVGPath(svgPath);
        gc.stroke();
        gc.restore();
    }

    private void clear() {
        gc.setFill(BG);
        gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
    }

    public static void main(String[] args) {
        launch(CanvasSVG.class);
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045