如何使用JavaFXWebView从SVG图像生成图像

如何使用JavaFXWebView从SVG图像生成图像,java,svg,javafx,Java,Svg,Javafx,我有一个svg文件,我想从中创建一个用于画布的图像 下面的示例创建一个WebView,获取相应的WebEngine并加载svg内容。然后使用快照创建映像 正确的显示不应该有白色矩形,因为椭圆图像的区域应该是透明的。这有两个主要问题: 生成的图像具有不透明的背景 我需要显示一个包含WebView的阶段,以便绘制图形 导入javafx.application.application; 导入javafx.scene.Parent; 导入javafx.scene.scene; 导入javafx.sce

我有一个svg文件,我想从中创建一个用于画布的图像

下面的示例创建一个WebView,获取相应的WebEngine并加载svg内容。然后使用快照创建映像

正确的显示不应该有白色矩形,因为椭圆图像的区域应该是透明的。这有两个主要问题:

  • 生成的图像具有不透明的背景
  • 我需要显示一个包含WebView的阶段,以便绘制图形
    导入javafx.application.application;
    导入javafx.scene.Parent;
    导入javafx.scene.scene;
    导入javafx.scene.layout.ancorpane;
    导入javafx.stage.stage;
    导入javafx.animation.AnimationTimer;
    导入javafx.scene.paint.Color;
    导入javafx.scene.canvas.GraphicsContext;
    导入javafx.scene.canvas.canvas;
    导入javafx.scene.web.WebEngine;
    导入javafx.scene.web.WebView;
    导入javafx.scene.Snapshot参数;
    导入javafx.scene.SnapshotResult;
    导入javafx.scene.image.image;
    公共类SvgWebView扩展了应用程序{
    画布=新画布(512);
    动画定时器加载器;
    public void start(Stage primaryStage)引发异常{
    loadGraphics();
    锚烷根=新锚烷(帆布);
    setTitle(“来自webview的Svg”);
    场景=新场景(根,640,640);
    初级阶段。场景(场景);
    primaryStage.show();
    }
    Void setImage(快照结果){
    Image img=result.getImage();
    GraphicsContext g2d=canvas.getGraphicsContext2D();
    g2d.设置填充(颜色:黑色);
    g2d.fillRect(0,0,512,512);
    g2d.绘图图像(img,192129);
    loader.stop();
    返回null;
    }
    公共void loadGraphics(){
    WebView视图=新建WebView();
    场景精灵=新场景(视图,128,128);
    WebEngine=view.getEngine();
    String content=“”+
    "";
    loadContent(内容,“image/svg+xml”);
    发动机。重新加载();
    Stage s=新建Stage();//创建映像所必需的。
    s、 雪碧;
    s、 show();
    loader=新的AnimationTimer(){
    长计数=0;
    公共无效句柄(长){
    如果(计数+==2){
    //从链接问题开始解决问题
    SnapshotParameters params=新的SnapshotParameters();
    参数设置填充(颜色透明);
    view.snapshot(rlt->setImage(rlt),参数,null);
    loader.stop();
    s、 隐藏();
    }
    }
    };
    loader.start();
    }
    }
    
    这个问题类似于,但更为具体,因为我实际上正在研究提出的解决方案之一

    根据此问题使用动画计时器,它似乎是必要的

    使用JavaFX11.0.2和14.0.1,在OSX上测试了“openjdk版本”11.0.6

    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();
    
        }
    
    }