2016-08-04 58 views
1

使用JavaFX,我试图将阴影和反射效果链接在一起,将文本绘制到画布上。将反射应用于JavaFX中的阴影效果

以下代码将显示反射的红色文本,然后将阴影应用于原始文本和反射文本。

Canvas canvas = new Canvas(400,400); 
GraphicsContext context = canvas.getGraphicsContext2D(); 
context.setFont(new Font("Arial Bold", 48)); 
context.setFill(Color.RED); 
DropShadow shadow = new DropShadow(6, 2, 2, Color.BLACK); 
Reflection reflect = new Reflection(10, 1.0, 1.0, 0.0); 
shadow.setInput(reflect); 
context.setEffect(shadow); 
context.fillText("Hello, world!", 100,100); 

但是,投影在反射中出现“向后”,因为需要首先应用阴影以获得逼真的效果。我试图通过颠倒在其中的影响的应用顺序,通过从上方改变setInputsetEffect行的代码来完成这个如下:

reflect.setInput(shadow); 
context.setEffect(reflect); 

但是,结果是仅反射被施加;我根本看不到任何投影。

为什么不投射阴影/不可见?

如何重写此代码以实现所需效果(如果可能,只能使用效果的组合)?

回答

1

我不知道你说什么可以通过使用GraphicsContext与标准的API来实现,所以欢迎其他答案。但是,这可能是一个临时解决方法,只要它实际上是您所需要的。首先应用阴影,然后逐个像素地复制图像以模仿反射效果。请参阅以下屏幕截图:(原始 - 左侧,新 - 右侧)。

Reflection

全部工作实施例在下面附接。它需要一些调整来获得一个通用的解决方案,但应该有足够的开始。

import javafx.application.Application; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.canvas.Canvas; 
import javafx.scene.canvas.GraphicsContext; 
import javafx.scene.effect.DropShadow; 
import javafx.scene.effect.Effect; 
import javafx.scene.image.WritableImage; 
import javafx.scene.layout.Pane; 
import javafx.scene.paint.Color; 
import javafx.scene.text.Font; 
import javafx.scene.text.Text; 
import javafx.stage.Stage; 

public class FXApp extends Application { 

    private Parent createContent() { 
     Canvas canvas = new Canvas(400,400); 

     Font font = new Font("Arial Bold", 48); 
     Color fill = Color.RED; 
     DropShadow shadow = new DropShadow(6, 2, 2, Color.BLACK); 

     fillTextWithReflection(canvas.getGraphicsContext2D(), "Hello, world!", 100, 100, font, fill, shadow); 

     return new Pane(canvas); 
    } 

    private void fillTextWithReflection(GraphicsContext g, String text, double textX, double textY, Font font, Color fill, Effect effect) { 
     Text t = new Text(text); 
     t.setFont(font); 

     // 5 px margin 
     Canvas tmpCanvas = new Canvas(t.getLayoutBounds().getWidth() + 5, t.getLayoutBounds().getHeight() + 5); 

     // set configuration 
     GraphicsContext tmpContext = tmpCanvas.getGraphicsContext2D(); 
     tmpContext.setFont(font); 
     tmpContext.setFill(fill); 
     tmpContext.setEffect(effect); 

     // draw on temporary context 
     tmpContext.fillText(text, 0, font.getSize()); 

     // take a snapshot of the text 
     WritableImage snapshot = tmpCanvas.snapshot(null, null); 

     int w = (int)snapshot.getWidth(); 
     int h = (int)snapshot.getHeight(); 

     WritableImage reflected = new WritableImage(w, h); 

     // make an 'inverted' copy 
     for (int y = 0; y < h; y++) { 
      // imitate fading out of reflection 
      double alpha = y/(h - 1.0); 

      for (int x = 0; x < w; x++) { 
       Color oldColor = snapshot.getPixelReader().getColor(x, y); 
       Color newColor = Color.color(oldColor.getRed(), oldColor.getGreen(), oldColor.getBlue(), alpha); 

       reflected.getPixelWriter().setColor(x, h - 1 - y, newColor); 
      } 
     } 

     // draw on the actual context 
     // images are drawn from x, y top-left but text is filled from x, y + h 
     // hence corrections 
     // this can be replaced with actual fillText() call if required 
     g.drawImage(snapshot, textX, textY - font.getSize()); 
     g.drawImage(reflected, textX, textY + h - font.getSize()); 
    } 

    @Override 
    public void start(Stage stage) throws Exception { 
     stage.setScene(new Scene(createContent())); 
     stage.show(); 
    } 
} 
+0

感谢你 - 你已经基本上改写了图像效果从头开始,似乎!然而,我主要感兴趣的是为什么我的代码不能正常工作,并且想知道是否可以仅使用效果组合来实现所需的效果。我已经更新了我的问题,以便更清楚。但是,谢谢你的努力! –