2016-08-04 13 views
1

JavaFXを使用して、ドロップシャドウと反射エフェクトを一緒に連結してキャンバスにテキストを描画しようとしています。JavaFXでDropShadowエフェクトにリフレクションを適用する

次のコードでは、赤いテキストが反映され、元のテキストと反映されたテキストにドロップシャドウが適用されます。

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

標準APIでGraphicsContextを使用すると、あなたの言うことが達成できるかどうかわかりません。他の回答も歓迎します。ただし、実際に必要なものであれば、これは一時的な回避策である可能性があります。シャドウが最初に適用され、イメージが反射効果を模倣するためにピクセルごとにコピーされます。以下のスクリーンショットをご覧ください:(オリジナル - 左は新しい、右は - )

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

ありがとうございます - 基本的に画像の効果を最初から書き直しました。しかし、私は主に与えられたコードが機能していない理由に興味があり、効果の構成のみを使用して目的の効果を達成できるかどうかを知りたい。上記の私の質問をもっと明確に更新しました。しかし、あなたの努力のおかげですべて同じ! –

関連する問題