I came across the cool blog by Rakesh Menon the other day “JavaFX – Text Effects”. It got me thinking how many other cool text effects could we do in JavaFX. Quick research for ideas came up with “50 Stunning Photoshop Text Effect Tutorials” blog post on Smashing Magazine. So I picked a couple fun ones and had a go 🙂
Neon Text
The first example the came to my attention as I could see how I could have used it in our recent game, was Neon Text @ spoono.com. This is achieved in JavaFX by applying multiple innershadow and dropshadow effects to the text. Here is the complete code for the test application above.
[jfx]
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.*;
import javafx.scene.image.*;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import javafx.scene.effect.*;
import javafx.scene.control.*;
var width = 600;
var height = 300;
var text:Text;
var textBox:TextBox;
Stage {
title: "Text Effects: Neon Sign"
resizable: false
scene: Scene {
width: width, height: height
content: [
ImageView { image: Image{ url: "{__DIR__}bricks.jpg"} }
Rectangle {
width: width, height: height
fill: RadialGradient {
centerX: 0.5, centerY: 0.5
radius: 0.7, proportional: true
stops: [
Stop{offset: 0.4, color: Color.rgb(0,0,0,0.1)}
Stop{offset: 1, color: Color.rgb(0,0,0,0.8)}
]
}
}
text = Text {
effect: Blend{
mode: BlendMode.MULTIPLY
bottomInput: DropShadow {
color: Color.rgb(254,235,66,0.3)
offsetX: 5, offsetY: 5
radius: 5
spread: 0.2
}
topInput: Blend{
mode: BlendMode.MULTIPLY
bottomInput: DropShadow {
color: Color.web("#f13a00")
radius: 20
spread: 0.2
}
topInput: Blend{
mode: BlendMode.MULTIPLY
bottomInput: InnerShadow {
color: Color.web("#feeb42")
radius: 9
choke: 0.8
}
topInput: InnerShadow {
color: Color.web("#f13a00")
radius: 5
choke: 0.4
}
}
}
}
fill: Color.WHITE
font : Font { name: "Harlow" size : 110 }
layoutX: bind (width – text.layoutBounds.width)/2
layoutY: bind (height/2) + 20
content: bind textBox.rawText
}
textBox = TextBox {
text:"Neon Sign"
layoutX: 100
layoutY: height – 40
width: width-200
}
]
}
}
[/jfx]
Snow & Ice
This one was based on the Tutsplus.com article Icey Styles in Photoshop but as we do not have the Bevel and Emboss effect that photoshop has yet I had do my best to simulate it with inner and drop shadows.
[jfx]
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.*;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import javafx.scene.effect.*;
import javafx.scene.control.*;
var width = 600;
var height = 400;
var text:Text;
var textBox:TextBox;
Stage {
title: "Text Effects: Snow & Ice"
resizable: false
scene: Scene {
width: width
height: height
content: [
Rectangle {
width: width, height: height
fill: RadialGradient {
centerX: 0.5, centerY: 0.5
radius: 0.7, proportional: true
stops: [
Stop{offset: 0.4, color: Color.web("#34365e")}
Stop{offset: 1, color: Color.web("#0d0f3a")}
]
}
}
text = Text {
effect: Blend{
mode: BlendMode.SRC_OVER
bottomInput: DropShadow {
color: Color.rgb(0,0,0,0.1)
offsetX: 8, offsetY: 8
radius: 2
}
topInput: Blend{
mode: BlendMode.SRC_OVER
bottomInput: DropShadow {
color: Color.web("#21233f")
radius: 4
spread: 0.9
}
topInput: Blend{
mode: BlendMode.DARKEN
bottomInput: InnerShadow {
color: Color.web("#cee3f4")
radius: 5
choke: 0.7
offsetX: -4, offsetY: -4
}
topInput: Blend{
mode: BlendMode.MULTIPLY
bottomInput: InnerShadow {
color: Color.web("#6c7fee")
radius: 7
choke: 0.2
offsetX: 2, offsetY: 2
}
topInput: InnerShadow {
color: Color.web("#a5ebff")
radius: 4
offsetX: -2, offsetY: -2
}
}
}
}
}
fill: Color.web("#f7fafb")//web("#e5f5fb")
strokeWidth: 3
font : Font {
name: "Kabel"
size : 120
}
layoutX: bind (width – text.layoutBounds.width)/2
layoutY: bind (height/2) – 20
content: bind if (textBox.rawText == "") then "Snow \n& Ice" else textBox.rawText
}
textBox = TextBox {
layoutX: 100
layoutY: height – 40
width: width-200
}
]
}
}
[/jfx]
Recessed
After playing with a couple from tutorials I thought I would have a go at one my self. This is a version of the classic web recessed text effect. The designer Alex Buga used this technique to great effect on his website. Unfortunately its down for redesign at the moment but for those who missed it here is a snap shot.
Here is the code for this sample. Its much simpler than the first two as it only uses two effects and a gradient fill on the text. It could be applied to any color just by changing the text fill gradient to be darker version of the background it is sitting on.
[jfx]
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.*;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import javafx.scene.effect.*;
import javafx.scene.control.*;
var width = 600;
var height = 300;
var text:Text;
var textBox:TextBox;
Stage {
title: "Text Effects: Recessed"
resizable: false
scene: Scene {
width: width
height: height
content: [
Rectangle {
width: width, height: height
fill: LinearGradient {
startX: 0, endX: 0, startY: 0, endY: 1
stops: [
Stop { offset: 0, color: Color.rgb(202,202,202) }
Stop { offset: 1, color: Color.rgb(97,97,97) }
]
}
}
text = Text {
effect: Blend{
mode: BlendMode.MULTIPLY
bottomInput: DropShadow {
color: Color.rgb(255,255,255,0.5)
offsetX: 1, offsetY: 1
radius: 0
}
topInput: InnerShadow {
color: Color.rgb(0,0,0,0.7)
offsetX: 2, offsetY: 2
radius: 5
}
}
fill: LinearGradient {
startX: 0, endX: 0, startY: 0, endY: 1
stops: [
Stop { offset: 0, color: Color.rgb(190,190,190) }
Stop { offset: 1, color: Color.rgb(170,170,170) }
]
}
font : Font { name: "Arial Black", size : 90 }
layoutX: bind (width – text.layoutBounds.width)/2
layoutY: bind (height/2) + 20
content: bind textBox.rawText
}
textBox = TextBox {
text:"Recessed"
layoutX: 100
layoutY: height – 40
width: width-200
}
]
}
}
[/jfx]
Stand Out
One last little example for you, this one is going for a chrome look. This only uses a single simple reflection effect most of it is done with a gradient fill and gradient stroke.
[jfx]
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.*;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import javafx.scene.effect.*;
import javafx.scene.control.*;
var width = 600;
var height = 300;
var text:Text;
var textBox:TextBox;
Stage {
title: "Text Effects: Stand Out"
resizable: false
scene: Scene {
width: width
height: height
content: [
Rectangle {
width: width, height: height
fill: LinearGradient {
startX: 0, endX: 0, startY: 0, endY: 1
stops: [
Stop { offset: 0, color: Color.web("#6c6a6a") }
Stop { offset: 1, color: Color.web("#3e3d3d") }
]
}
}
text = Text {
effect: Reflection {
topOffset: -4
}
fill: LinearGradient {
startX: 0, endX: 0, startY: 0, endY: 1
stops: [
Stop { offset: 0.03, color: Color.web("#cccccc") }
Stop { offset: 0.499, color: Color.web("#fdfdfd") }
Stop { offset: 0.5, color: Color.web("#999999") }
Stop { offset: 0.99, color: Color.web("#dddddd") }
]
}
stroke: LinearGradient {
startX: 0, endX: 0, startY: 0, endY: 1
stops: [
Stop { offset: 0.03, color: Color.web("#e9e5e5") }
Stop { offset: 0.06, color: Color.web("#909090") }
Stop { offset: 0.23, color: Color.web("#d1d1d1") }
Stop { offset: 0.34, color: Color.web("#9f9f9f") }
Stop { offset: 0.60, color: Color.web("#7b7b7b") }
Stop { offset: 0.67, color: Color.web("#aeaeae") }
Stop { offset: 0.76, color: Color.web("#7b7b7b") }
Stop { offset: 0.94, color: Color.web("#676766") }
Stop { offset: 0.99, color: Color.web("#e5e5e4") }
]
}
font : Font { name: "Arial Black", size : 80 }
layoutX: bind (width – text.layoutBounds.width)/2
layoutY: bind (height/2) + 20
content: bind textBox.rawText
}
textBox = TextBox {
text:"STAND OUT"
layoutX: 100
layoutY: height – 40
width: width-200
}
]
}
}
[/jfx]
I hope you have enjoyed these 🙂 Have a go see what you can create your self it would be great to be able to put together a “50 Stunning JavaFX Text Effect Tutorials” blog.
Wow, nice work. When I see this I immediately think “multi-look text component.” How do you think you would pull this out into a reusable API so we could just plug in the look we wanted?
Patrick
I started merging all the demos onto one file but decided it was simpler to follow separated. The backgrounds are separate think to solve as that depends on the use or the text. The rest is simple to extract and make generic as its only 5 settings: effect,fill, stroke, strokeWidth and font.
I would hope that once we have support for effects in our new CSS engine we all of these could be done with CSS styles which would rock 🙂
Wow! I am impressed about the great effects. This really brings JavaFX to a point, where it is of great use for graphics designers. Here you notice the huge difference in UI compared to plain “old Java applets”. This examples rock! 🙂
Kind regards,
Herbert
Hi,
Recessed demo doesn’t seem to work. No output when text is typed in the textfield. The rest of the demos are working fine though.
I was wondering if that will crop up as I saw same issue on my wife’s PC laptop. But asked a few other people to try it and it worked fine for them. My guess its a issue finding “Arial Black” font. Does Stand Out one work for you which uses same font?
StandOut works, but Recessed does not. (Vista Professional)
Stand Out works for me but Recessed does not display any text (Win XP, IE).
Jasper,
when running under Windows 7, the Recessed demo does not work. However, by removing the following section from the code, the text will appear (so I doubt that font is the issue). Is there a problem when Blend and LinearGradient are used together under Windows ?
fill: LinearGradient {
startX: 0, endX: 0, startY: 0, endY: 1
stops: [
Stop { offset: 0, color: Color.rgb(190,190,190) }
Stop { offset: 1, color: Color.rgb(170,170,170) }
]
}
All the demos work fine using NetBeans except for Recessed.
Thanks, I have emailed the guys working on effects to see if they can find the issue. Will let you know 🙂
The problem with Recessed demo is fixed in the next JavaFX release. It was likely caused by a known bug in the jdk with gradients.
Dmitri
which language it is and how can i use it .. i write it in javafx program i is not working
The language is JavaFX Script. It is the language JavaFX used to be in prior to version 2. You can run with with JavaFX 1.3 or it should be very simple to port to JavaFX 2. You just need to map the setting of properties to Java set…() method calls. I think there were some conversion tools around on the web as well.