在我的主应用程序中,我有一些添加到XYChart的SVGPath。有时他们有一个ImagePattern填充,现在需要具有LinearGradient填充。 ImagePattern填充是一个交叉阴影线,需要使用LinearGradient对其进行着色,就像它是应用了LinearGradient的纯矩形矩形一样。 SVGPath也具有虚线轮廓,而LinearGradient应该填充虚线轮廓和ImagePattern填充,因为它们是同一形状的一部分。
我已经写了一些示例代码来显示我的位置。这会在创建交叉阴影线时为其着色,并且看起来还可以,但是我上面描述的效果不佳,因为ImagePattern中的每个交叉线都分别应用了LinearGradient。理想情况下,一旦应用了ImagePattern填充,则将LinearGradient仅应用于最终的SVGPath。 我还尝试了使用Blend和ColorInput进行一些效果,但没有设法进一步解决该问题。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.image.Image;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.ImagePattern;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Paint;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Line;
import javafx.scene.shape.SVGPath;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
List<Color> colors = Arrays.asList(Color.RED, Color.YELLOW, Color.GREEN);
ArrayList<Stop> stops = new ArrayList<>(colors.size() * 2);
for (int i = 0; i < colors.size(); i++) {
stops.add(new Stop(getOffset(i, colors.size()), colors.get(i)));
stops.add(new Stop(getOffset(i + 1, colors.size()), colors.get(i)));
}
LinearGradient lg = new LinearGradient(0, 0, 20, 20, false, CycleMethod.REPEAT, stops);
SVGPath svgPath = new SVGPath();
svgPath.setContent("M-84.1487,-15.8513 a22.4171,22.4171 0 1 0 0,31.7026 h168.2974 a22.4171,22.4171 0 1 0 0,-31.7026 Z");
Image hatch = createCrossHatch(lg);
ImagePattern pattern = new ImagePattern(hatch, 0, 0, 10, 10, false);
svgPath.setFill(pattern);
svgPath.setStroke(lg);
BorderPane root = new BorderPane();
root.setCenter(svgPath);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
catch (Exception e) {
e.printStackTrace();
}
}
protected static Image createCrossHatch(Paint paint) {
Pane pane = new Pane();
pane.setPrefSize(20, 20);
pane.setStyle("-fx-background-color: transparent;");
Line fw = new Line(-5, -5, 25, 25);
Line bw = new Line(-5, 25, 25, -5);
fw.setStroke(paint);
bw.setStroke(paint);
fw.setStrokeWidth(3);
bw.setStrokeWidth(3);
pane.getChildren().addAll(fw, bw);
new Scene(pane);
SnapshotParameters sp = new SnapshotParameters();
sp.setFill(Color.TRANSPARENT);
return pane.snapshot(sp, null);
}
private double getOffset(double i, int count) {
return (((double) 1) / (double) count * (double) i);
}
public static void main(String[] args) {
launch(args);
}
}
如果运行提供的代码,您将看到它画出一条狗骨头。虚线轮廓线的线性渐变颜色应继续穿过阴影线的ImagePattern填充。我知道为什么阴影的ImagePattern像这样着色,但这是我目前最好的折衷方案。如前所述,我希望能够在应用ImagePattern填充后将LinearGradient填充应用于整个形状,以便LinearGradient对整个形状产生相同的影响。
谢谢
答案 0 :(得分:0)
没有直接方法可以在一个节点上应用和组合两种涂料。我们可以通过CSS使用背景色叠加许多不同的paints(例如,实心,线性渐变甚至是图像图案),但不会结合使用。
因此,为了组合两种不同的绘画,一方面是线性渐变,另一方面是图案填充,我们需要将它们应用于两个节点,并在两种绘画之间使用混合效果。
根据发布的代码,这是具有线性渐变的SVGPath:
@Override
public void start(Stage primaryStage) {
Node base = getNodeWithGradient();
BorderPane root = new BorderPane();
Group group = new Group(base);
root.setCenter(group);
Scene scene = new Scene(root, 400, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
private SVGPath getNodeWithGradient() {
List<Color> colors = Arrays.asList(Color.RED, Color.YELLOW, Color.GREEN);
ArrayList<Stop> stops = new ArrayList<>(colors.size() * 2);
for (int i = 0; i < colors.size(); i++) {
stops.add(new Stop(getOffset(i, colors.size()), colors.get(i)));
stops.add(new Stop(getOffset(i + 1, colors.size()), colors.get(i)));
}
LinearGradient lg = new LinearGradient(0, 0, 20, 20, false, CycleMethod.REPEAT, stops);
SVGPath svgPath = getSVGPath();
svgPath.setFill(lg);
svgPath.setStroke(lg);
return svgPath;
}
private SVGPath getSVGPath() {
SVGPath svgPath = new SVGPath();
svgPath.setContent("M-84.1487,-15.8513 a22.4171,22.4171 0 1 0 0,31.7026 h168.2974 a22.4171,22.4171 0 1 0 0,-31.7026 Z");
return svgPath;
}
private double getOffset(double i, int count) {
return (((double) 1) / (double) count * (double) i);
}
这是带有图像图案填充的SVGPath:
@Override
public void start(Stage primaryStage) {
Node overlay = getNodeWithPattern();
BorderPane root = new BorderPane();
Group group = new Group(overlay);
root.setCenter(group);
Scene scene = new Scene(root, 400, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
private SVGPath getNodeWithPattern() {
Image hatch = createCrossHatch();
ImagePattern pattern = new ImagePattern(hatch, 0, 0, 10, 10, false);
SVGPath svgPath = getSVGPath();
svgPath.setFill(pattern);
return svgPath;
}
private SVGPath getSVGPath() {
SVGPath svgPath = new SVGPath();
svgPath.setContent("M-84.1487,-15.8513 a22.4171,22.4171 0 1 0 0,31.7026 h168.2974 a22.4171,22.4171 0 1 0 0,-31.7026 Z");
return svgPath;
}
private static Image createCrossHatch() {
Pane pane = new Pane();
pane.setPrefSize(20, 20);
Line fw = new Line(-5, -5, 25, 25);
Line bw = new Line(-5, 25, 25, -5);
fw.setStroke(Color.BLACK);
bw.setStroke(Color.BLACK);
fw.setStrokeWidth(3);
bw.setStrokeWidth(3);
pane.getChildren().addAll(fw, bw);
new Scene(pane);
SnapshotParameters sp = new SnapshotParameters();
return pane.snapshot(sp, null);
}
现在的诀窍是将两个SVGPath节点组合在一起,在其顶部添加一种混合模式。
根据BlendMode.ADD
的{{3}}:
顶部输入的颜色和alpha分量被添加到底部输入的颜色和alpha分量。
@Override
public void start(Stage primaryStage) {
Node base = getNodeWithGradient();
Node overlay = getNodeWithPattern();
overlay.setBlendMode(BlendMode.ADD);
BorderPane root = new BorderPane();
Group group = new Group(base, overlay);
root.setCenter(group);
Scene scene = new Scene(root, 400, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
private SVGPath getNodeWithGradient() {
List<Color> colors = Arrays.asList(Color.RED, Color.YELLOW, Color.GREEN);
ArrayList<Stop> stops = new ArrayList<>(colors.size() * 2);
for (int i = 0; i < colors.size(); i++) {
stops.add(new Stop(getOffset(i, colors.size()), colors.get(i)));
stops.add(new Stop(getOffset(i + 1, colors.size()), colors.get(i)));
}
LinearGradient lg = new LinearGradient(0, 0, 20, 20, false, CycleMethod.REPEAT, stops);
SVGPath svgPath = getSVGPath();
svgPath.setFill(lg);
svgPath.setStroke(lg);
return svgPath;
}
private SVGPath getNodeWithPattern() {
Image hatch = createCrossHatch();
ImagePattern pattern = new ImagePattern(hatch, 0, 0, 10, 10, false);
SVGPath svgPath = getSVGPath();
svgPath.setFill(pattern);
return svgPath;
}
private SVGPath getSVGPath() {
SVGPath svgPath = new SVGPath();
svgPath.setContent("M-84.1487,-15.8513 a22.4171,22.4171 0 1 0 0,31.7026 h168.2974 a22.4171,22.4171 0 1 0 0,-31.7026 Z");
return svgPath;
}
private static Image createCrossHatch() {
Pane pane = new Pane();
pane.setPrefSize(20, 20);
Line fw = new Line(-5, -5, 25, 25);
Line bw = new Line(-5, 25, 25, -5);
fw.setStroke(Color.BLACK);
bw.setStroke(Color.BLACK);
fw.setStrokeWidth(3);
bw.setStrokeWidth(3);
pane.getChildren().addAll(fw, bw);
new Scene(pane);
SnapshotParameters sp = new SnapshotParameters();
return pane.snapshot(sp, null);
}
private double getOffset(double i, int count) {
return (((double) 1) / (double) count * (double) i);
}
我们得到了预期的结果: