I have an svg file, and I would like to create an Image from it for use on a Canvas.
The following example, creates a WebView gets the corresponding WebEngine and loads the svg content. Then a snapshot is used to create an image.
The correct display should not have the white rectangle because that region of the ellipse image should be transparent. This has two main issues:
- The resulting Image has an opaque background.
- I need to display a Stage containing the WebView for the graphics to be drawn.
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import javafx.animation.AnimationTimer;
import javafx.scene.paint.Color;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.canvas.Canvas;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.scene.SnapshotParameters;
import javafx.scene.SnapshotResult;
import javafx.scene.image.Image;
public class SvgWebView extends Application{
Canvas canvas = new Canvas(512, 512);
AnimationTimer loader;
public void start(Stage primaryStage) throws Exception{
loadGraphics();
AnchorPane root = new AnchorPane(canvas);
primaryStage.setTitle("Svg from webview");
Scene scene = new Scene(root, 640, 640);
primaryStage.setScene(scene);
primaryStage.show();
}
Void setImage(SnapshotResult result){
Image img = result.getImage();
GraphicsContext g2d = canvas.getGraphicsContext2D();
g2d.setFill(Color.BLACK);
g2d.fillRect(0, 0, 512, 512);
g2d.drawImage(img, 192, 129);
loader.stop();
return null;
}
public void loadGraphics(){
WebView view = new WebView();
Scene sprites = new Scene(view, 128, 128);
WebEngine engine = view.getEngine();
String content = "<svg width=\"128px\" height=\"128px\" viewBox=\"0 0 128 129\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">" +
"<ellipse cx=\"64px\" cy=\"64px\" rx=\"64px\" ry=\"32px\" stroke=\"#f00\" fill=\"#00f\"/></svg>";
engine.loadContent(content, "image/svg+xml");
engine.reload();
Stage s = new Stage( ); //necessary to create image.
s.setScene(sprites);
s.show();
loader = new AnimationTimer(){
long count = 0;
public void handle(long now){
if( count++ == 2 ){
//work around from linked question
SnapshotParameters params = new SnapshotParameters();
params.setFill(Color.TRANSPARENT);
view.snapshot( rlt->setImage(rlt), params, null);
loader.stop();
s.hide();
}
}
};
loader.start();
}
}
This question is similar to SVG Image in JavaFX 2.2 but it is more specific, in that I am actually looking at one of the solutions proposed.
The animation timer is used as per this question JavaFX 2.0+ WebView /WebEngine render web page to an image and it does appear to be necessary.
tested on OSX with 'openjdk version "11.0.6"' using both javafx 11.0.2 and 14.0.1