How to set radial-gradient with css in javafx - javafx-2

I have a Label. Try to set radial-gradient in my css for this lable.
How can i do it right?
If i set -fx-background-color: radial-gradient(center 50% 50%, radius 50%, rgb(104, 163, 193) 0%, rgb(23, 56, 99) 100%); - I receive an error "mismatched parameters"
Thanks for any help!

Setting gradients for Shapes
Here is an example I pulled from a small clock widget I wrote a long time ago:
-fx-fill: radial-gradient(radius 180%, burlywood, derive(burlywood, -30%), derive(burlywood, 30%));
The gradient shows up as the circular shading on the clockface just below the center of the clock.
Setting gradients for Labels
As you are using a label, the corresponding css attribute to use to shade the text of the label would be -fx-text-fill for the foreground text and -fx-background-color for the text background.
Here is a sample with -fx-text-fill and -fx-background-color styles applied to a label. The radial gradient used for the background is the same radial gradient that was used for the clock face.
Label label = new Label("xyzzy");
label.setStyle("-fx-background-color: radial-gradient(radius 180%, burlywood, derive(burlywood, -30%), derive(burlywood, 30%)); -fx-text-fill: white;");
Actual parameters to use for your gradient depends on your application
Of course, the configuration of radial gradients will vary depending upon exactly what gradient you wish to draw. Documentation for the syntax an construction of an expression to assign a radial gradient via css is contained in the JavaFX 8 CSS reference guide.

Related

Responsive base64 images

How do I scale the following base64 image (a background pattern) with transform:scale() or with other methods so, that the pattern would have the same ratio on screens with different resolutions?
Chrome Dev Tools shows that this is a 4x4 px image.
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAH0lEQVQYV2NkQAX/GZH4/xkYGBhhAmAOSBJEwDkgAQCCrgQEjpMcPgAAAABJRU5ErkJggg==) repeat
I want to use transform:scale() or other methods to define the size of the image in viewport units instead of pixels, so that the pattern would have the same ratio on all screens.
Do I need to transform it into SVG instead?
Okay, so I realized that it's possible to do something like this:
background: linear-gradient( rgba(10, 14, 15, 0.60), rgba(10, 14, 15, 0.60) ),url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAH0lEQVQYV2NkQAX/GZH4/xkYGBhhAmAOSBJEwDkgAQCCrgQEjpMcPgAAAABJRU5ErkJggg==) repeat;
background-size: 0.4vw 0.4vw;
But the background pattern is smudgy, not as uniform.

What is the default SVG unit in CSS?

I would like to convert a transform SVG attribute into a CSS transform. Here it is:
<g transform="translate(11.225 164)"/>
But CSS requires me to specify units. What is the correct unit to specify? Since it's supposed to be a library, I don't know the width, height or viewport of the <svg>. Thus I can't compute the px or so.
The default (user) unit is px.
One px unit is defined to be equal to one user unit. Thus, a length of "5px" is the same as a length of "5".
Per the SVG specification

Rendering Text with Signed Distance Fields in WebGL

Core Problem:
I want to render Text in WebGL.
I don't want to do this via an "overlayed" HTML DOM Element.
I want the actual text rendering to happen inside WebGL.
Initial Solution 1
Render each character as a high number of quads.
This is not good as I need to render many characters.
Initial Solution 2 (implemented + tried this one).
Using Canvas, render all characters into an "atlas/map".
Convert Canvas into a WebGL Texture.
When I need to render a character, just pull it from the Texture.
Problem: Even if the Canvas renders the font at font size 80, and the WebGL renders the font at font size 20, it's still blurry due to various forms of antialiasing, interpolation, and whatever else post processing.
What I think is the right solution. (Not sure, may be wrong on this).
Signed Distance Field: https://www.youtube.com/watch?v=CGZRHJvJYIg
For every pixel, store distance to nearest border.
Question
I am having trouble finding any WebGL implementation of Signed Distance Fields.
Can SDFs work with WebGL, or is there some limitation of WebGL which prevents SDFs from working.
If so, is there some library that will take are of:
actual shader for rendering SDF AND
can take a font and produce the SDFs necessary for rendering?
EDIT: Can someone please verify that the following is a COMPLETE SDF shader?
(copied from https://www.mapbox.com/blog/text-signed-distance-fields/ )
precision mediump float;
uniform sampler2D u_texture;
uniform vec4 u_color;
uniform float u_buffer;
uniform float u_gamma;
varying vec2 v_texcoord;
void main() {
float dist = texture2D(u_texture, v_texcoord).r;
float alpha = smoothstep(u_buffer - u_gamma, u_buffer + u_gamma, dist);
gl_FragColor = vec4(u_color.rgb, alpha * u_color.a);
}
Yes, SDF's perfectly suitable for a WebGL application. For example, Mapbox uses it. The post actually contains SDF shader since it's incredibly simple.
To the second part of your question: it's better to prepare SDF texture for a font beforehand, and there're instruments to do exactly that. This one, for example.

How do I rotate or scale (transform) an SVG path relative to its center point?

I'm trying to rotate and scale shapes within an SVG around their center point. I've looked into several libraries, including Jquery, Greensock, D3, RaphaelJS, but I haven't been able to find any that provide a straightforward way to accomplish this. Each animates the shape from the origin point (which I understand is the default). I want to be able to spin a shape around its center point or scale it up or down from the center point.
Here are a couple examples using Greensock and D3 that illustrate the default behavior: http://jsbin.com/AHEXiPa/1/edit?html,js,output
Each of these examples bounce in and out from the top left as opposed to remaining stationary and expanding from the center of the triangle out in all directions.
Can one of the libraries I mentioned accomplish this, or is there another library or method I should consider?
Ideally, I need to be able to apply the animation/transform to an existing object in the DOM. D3 is good at this for instance, but Raphael seems to require converting an SVG to Raphael first prior to injecting it into the DOM.
Really its a case of pick the library that suits your needs, and then you will figure a way. As BigBadaboom says, if you do a search, there are lots of solutions.
To try and combine your questions, as sometimes the tricky bit is using an existing DOM object, I've included an example in Snap.svg. You can often do something similar in most libraries.
jsfiddle here Fiddle using your existing html.
s = Snap("#mySVGContainer1"); // create a canvas from existing svg
var triangle1 = s.select("#myShape1").transform("r90"); //select&transform existing object
p = Snap("#mySVGContainer2");
var triangle2 = p.select("#myShape2");
var bbox = triangle2.getBBox(); //bounding box, centre cx/cy
//rotate and scale with transform string (raphael/snap format)
triangle2.animate({ transform: "r180," + bbox.cx + ',' + bbox.cy + "s3,3," + bbox.cx + "," + bbox.cy }, 2000);
For rotations, as #Ian points out, you can specify the center of rotation. For other transformations, changes are defined relative to the path's (0,0) point.
The easiest way to get transformations to work relative to the path's center is to either:
Define the path so that it is centered around the (0,0) point; or
Wrap the path in a <g> element, and then translate it so it is centered on the (0,0) point of the <g> element's coordinate system.
Then, you can apply rotations, scales and transforms (on the <g> element, if using) and they will all be nicely centred.
The trickiest part is figuring out the "center" of an arbitrary shape. #Ian's approach of using the center of the bounding box will usually give decent results. If your shape is a polygon there are d3 functions you could use.
Example showing a shape moving with the mouse, rotating and changing scale, all centered around the center of the bounding box:
http://fiddle.jshell.net/LgfE3/
Edit: simplier jsfiddle
I've been looking for a long time, and will settle for the following.
1. Design your svg shape at coordinate x:0,y:0.
2. Identify by hand the center of rotation, by example, center = [ x:50,y:100].
3. Build a spinIt() function such :
function spinIt() {
needle.transition()
.duration(2000)
.attrTween("transform", tween);
function tween() {
return d3.interpolateString("rotate(-180, 50, 100)", "rotate(90, 50, 100)");
}
}
4. Use it on a triger:
svg.on("click", spinIt);
http://jsfiddle.net/SHF2M/79/

How do I get rid of the border around a split pane in JavaFX?

I'm using the JavaFX SceneBuilder, but I'll paste the FXML below since it's short. I have a very simple window with a split pane inside an anchor pane. Here is the FXML:
<?xml version="1.0" encoding="UTF-8"?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml">
<children>
<SplitPane id="main-split-pane" dividerPositions="0.25" focusTraversable="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="-1.0" prefWidth="-1.0" style="" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" style="" />
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" />
</items>
</SplitPane>
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
<stylesheets>
<URL value="#main-view.css" />
</stylesheets>
</AnchorPane>
I'm using the following CSS:
#main-split-pane {
-fx-border-style: none;
-fx-border-color: blue;
-fx-border-width: 25;
}
It gives me a windows like this:
I've played around with the CSS settings shown here, but there are a few things I'm having trouble understanding:
Where is the border I've marked with the red arrow coming from?
Why does setting the -fx-border-style to none cause the -fx-border-color to be ignored while the -fx-border-width still has an effect (like padding) on how things look?
Solution - How to remove a border from a Split Pane
Override the -fx-box-border color definition if you don't want the border to show:
split.setStyle("-fx-box-border: transparent;");
Split Pane with Border Removed
Sample Code
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class SplitPaneBorderRemover extends Application {
public static void main(String[] args) throws Exception { launch(args); }
#Override public void start(final Stage stage) throws Exception {
StackPane r1 = new StackPane();
r1.setPrefSize(200, 150);
r1.setStyle("-fx-background-color: palegreen;");
StackPane r2 = new StackPane();
r2.setPrefSize(200, 150);
r2.setStyle("-fx-background-color: coral;");
SplitPane split = new SplitPane();
split.getItems().setAll(
r1, r2
);
split.setStyle("-fx-box-border: transparent;");
StackPane layout = new StackPane();
layout.getChildren().setAll(split);
layout.setStyle("-fx-padding: 20px; -fx-background-color: cornsilk");
stage.setScene(new Scene(layout));
stage.show();
}
}
Answers to Additional Question
Where is the border I've marked with the red arrow coming from?
It's a background style in the default css stylesheet (caspian.css for JavaFX 2.2 or modena.css for Java 8)).
Why does setting the -fx-border-style to none cause the -fx-border-color to be ignored while the -fx-border-width still has an effect (like padding) on how things look?
Because the border of split pane is displayed using a background definition rather than border definition. All default JavaFX control css styles work this way. They set multiple overlaid backgrounds to accomplish border techniques rather than by setting an explicit border attribute.
Understanding How the Answer Works
Although this answer is really just a simple one liner, I'll take some time to explain here why it works. Sorry if this explanation bloats the answer. Those who already know this information can ignore this part of the answer.
I'm still having trouble understanding the concept
Spend some time reading the JavaFX css reference guide, a bit dry I know, but essential reading if you want to understand JavaFX css styling.
There is also an official Oracle tutorial for css, but it's not going to teach you as much as reading the css reference and studying the default style sheets I linked earlier.
I extracted relevant statements from the css reference and quoted them here:
JavaFX has a rich set of extensions to CSS in support of features such as color derivation, property lookup, and multiple background colors and borders for a single node. These features add significant new power for developers and designers and are described in detail in this document.
The -fx-box-border which is set to transparent to remove the border, is not really a border at all, it is a looked up color that has been applied to one of multiple backgrounds for the split-pane.
With looked-up colors you can refer to any other color property that is set on the current node or any of its parents. This is a very powerful feature, as it allows a generic palette of colors to be specified on the scene then used thoughout the application. If you want to change one of those palette colors you can do so at any level in the scene tree and it will affect that node and all its decendents. Looked-up colors are not looked up until they are applied, so they are live and react to any style changes that might occur, such as replacing a palette color at runtime with the "style" property on a node.
In the following example, all background color of all buttons uses the looked up color "abc".
.root { abc: #f00 }
.button { -fx-background-color: abc }
The default definition for -fx-box-border for the Java 8 modena.css style is:
/* A little darker than -fx-color and used to draw boxes around objects such
* as progress bars, scroll bars, scroll panes, trees, tables, and lists.
*/
-fx-box-border: ladder(
-fx-color,
black 20%,
derive(-fx-color,-15%) 30%
);
The default styling for a split-pane is as a "Box Like Thing":
/* ==== BOX LIKE THINGS ================================================= */
.scroll-pane,
.split-pane,
.list-view,
.tree-view,
.table-view,
.tree-table-view,
.html-editor {
-fx-background-color: -fx-box-border, -fx-control-inner-background;
-fx-background-insets: 0, 1;
-fx-padding: 1;
}
. . .
/* ones with grey -fx-background not lighter -fx-control-inner-background */
.scroll-pane,
.split-pane {
-fx-background-color: -fx-box-border, -fx-background;
}
So, analyzing the css, you can see that, for an unfocused split-pane there are two backgrounds defined (as the latest or most specific definition of -fx-background-color for .split-pane wins css's weird application rules). The inner background is colored as -fx-background and is inset one pixel. The outer background is colored as -fx-box-border and is not inset. Padding for the split pane is set to one pixel. This prevents the split pane content from overwriting the one pixel border around it.
The solution in this answer works by overriding the look-up color definition in code specifically for a a given splitpane instance by using the setStyle method. By setting the -fx-box-border to transparent (though perhaps null could have been used equally as well and might be more efficient), the border is set to be not visible (even though it is still there and the padding for it remains in the css at 1 pixel).
Further modification of the css (by applying your own user stylesheet to override the default split-pane style class) could remove this one pixel padding if desired:
.split-pane {
-fx-background-color: -fx-control-inner-background;
-fx-background-insets: 0;
-fx-padding: 0;
}
Now all trace of the border is gone and your content is free to fill the entire area of the split pane including the 1 pixel area where the border used to be. I prefer the minimal change of just setting the -fx-box-border to transparent though because then your user style definitions are small and don't detail a lot from the default style.
For example, set -fx-box-border: red; and you'll get a 1px red border around the split pane.
Yep, that's because the default background area the -fx-box-border color is coloring is only 1 pixel wide and you have just explicitly set the pixel color to red.
I assume it's the box-border on the padding component.
No, as described above the reason is because the background the -fx-box-border an inset of 0 pixels from the edge of the region and the inner background -fx-background-color is inset 1 pixel from the edge of the region, leaving 1 pixel width colored with the -fx-box-border. All the -fx-padding is doing in this instance is ensuring that your split pane content does not draw over the 1 pixel outer background for the split-pane.
Then set -fx-padding: 5; on split. The red box-border disappears and another gray border shows up.
The "gray border" was always there - it's the second, inner background defined in the split-pane css style (the -fx-background one). And the default -fx-background color is gray. By setting -fx-padding to 5 you are saying to inset the content of the split pane 5 pixels from the outside edge of the splitpane region. This allows the default background to show through.
If your content had some transparent areas and did not fill the whole available region of the split-pane, then you would also have seen this gray -fx-background-color color show through in those transparent areas.
If what you wanted was to achieve a 5 pixel border around your content in -fx-box-border color then you would need to adjust both the padding and the border insets, for example:
.split-pane {
-fx-background-color: -fx-box-border, -fx-control-inner-background;
-fx-background-insets: 0, 5;
-fx-padding: 5;
}
If the manual analysis of the padding, background insets, css style derivation rules, etc for a large application seems like it would be daunting, know that there is tool support to help understand both the scene graph structure and css application. The tools to use are SceneBuilder's css analyzer for design time css analysis and ScenicView for runtime scenegraph and css analysis.
If you want to remove the border around the split pane, but keep the ones for dividers, do this:
.split-pane {
-fx-background-color: transparent, -fx-background;
}

Resources