Showing posts with label canvas. Show all posts
Showing posts with label canvas. Show all posts

Sunday, December 12, 2021

A versus B

 Aloha,

last week I was searching the web for some comparison between an older iMac and an older Macbook Pro. And when I was skimming the web for such comparison pages I saw those comparison charts on some of the pages I've found.

Well I just checked "comparison chart" on Google and took a look at the images and found something like this:


And you will find a lot of similar charts on the web. This could be a really useful chart for some use cases and the best of all...it's really easy to implement :)

Long story short...here is my version of a ComparisonBarChart...


Just up front...the header with the "Product A" label and the "A" in the circle is NOT part of the chart. Because you not always need this labels I've decided to not add them to the chart itself but leave it to the user to add such things manually. So the chart only contains the bars and the categories.

More or less all of the chart is configurable, so here are just a few points that can be adjusted

- The colors of the background, the bars, the bar background, the text etc.

- The number format incl. no of decimals, percentage, shortened etc.


There are some things you have to keep in mind to make the chart and the comparison work. Because you can only compare options that are available on both things you try to compare, the charts takes 2 ChartItemSeries with identical number of items. Each item needs to have the category property set to a category. You need to use the same categories (at least they should have the same name) for both series and their items.

To create the sample above I first have created a list of categories. Then I've created 2 maps with the categories as key and the chart items as value. This can be done in one loop like this:

for (int i = 0 ; i < 5 ; i++) {
Category category = new Category("Option " + i);
categories.add(category);
optionsProductA.put(category, ChartItemBuilder.create().name("Product A (Option " + i + ")").category(category).value(0).build());
optionsProductB.put(category, ChartItemBuilder.create().name("Product B (Option " + i + ")").category(category).value(0).build());
}

Now you can create the ChartItemSeries by using it's builder and set the items to the e.g. new ArrayList<>(optionsProductA.values()).

To set the bar color for each series you can set the fill for the series for example to a LinearGradient or to a plain color.

Now you can create the ComparisonBarChart using it's builder as follows

chart = ComparisonBarChartBuilder.create(series1, series2)
.prefSize(600, 300)
.backgroundFill(Color.rgb(244, 250, 255))
.categoryBackgroundFill(new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE,
new Stop(0.0, Color.rgb(244, 250, 255)),
new Stop(0.05, Color.WHITE),
new Stop(0.95, Color.WHITE),
new Stop(1.0, Color.rgb(244, 250, 255))))
.barBackgroundFill(Color.rgb(232, 240, 252))
.barBackgroundVisible(true)
.shadowsVisible(true)
.textFill(Color.WHITE)
.categoryTextFill(Color.rgb(64, 66, 100))
.shortenNumbers(false)
.sorted(false)
.order(Order.DESCENDING)
.numberFormat(NumberFormat.PERCENTAGE)
.doCompare(false)
.categorySumVisible(false)
.betterColor(Color.BLUE)
.poorerColor(Color.RED)
.build();

To create the chart above you don't need to set all the options that you see in the code above. I've simply added it to show that they are available. For example .doCompare(false), .sorted(false), .categorySumVisible(false), .order(Order.DESCENDING) etc. are all not needed in this case.

If you only would like to compare two feature sets than this is all you need but if you would like to do more...well you can :)

You can for example sort the bars either ascending or descending by the sum of each category items. Meaning to say order it by the sum of the left and the right bar value of each category. This sum can also be shown by setting categorySumVisible to true.

If you set doCompare to true the color of the bars will change so that the one with the higher value (which is always be the "better" value in this chart) get's a different color than the bar with the smaller value (which always is the "poorer" value in this chart). There are some default colors like green for better and orange for poorer but these colors can also be set.

In addition you can also switch some visual effects on by setting shadowsVisible = true. This will add a shadow to each bar and also to the category area (the rectangle in the center of the chart).

If you don't really want to set all colors manually you will find 2 convenience methods for setting the bar colors which are setBetterColor() and setPoorerColor().

When calling these methods the poorerDarkerColor, poorerBrighterColor, betterDarkerColor and betterBrighterColor will automatically be set.

If you don't want to see a gradient for the bar fill you simply have to set the brighter and darker colors to the same values.

The easiest way to figure out how it works is to take a look at the ComparisonBarChartTest class.

This class contains the code for the screenshot above and should be starting point for your own version of the chart.

You will find this new ComparisonBarChart in the jdk17 branch of my JavaFX charts libray on github.

And of course it is also available on Maven Central...but keep in mind...you need to use JDK17 to run it...

That's it for today...so keep coding...


Tuesday, December 3, 2019

Some fun with JavaFX Canvas - SpaceFX

Aloha,

Last weekend I decided to write a little game because I never did that before. Saturday and Sunday morning I've spend some time to create a little space game where you have to dodge asteroids or shoot them. In addition there might be enemy ships that will fire back if you are in line of sight.
To realize that game I made use of the JavaFX Canvas node which seem to be a perfect fit for games like stuff.
In the Canvas node the redraw is in your hands (more or less) but at least you can decide when to redraw and how often. So what I did was to create an AnimationTimer and simply call a draw() method as often as possible (which usually should be around 60 times per second).
In this draw method I set the coordinates of all my objects and draw them, do the collision detection and play the sounds.
For the sprites I use simple images which I've found on the internet.
Long story short, here is a little video of the game...



If you hit an asteroid or an enemy ship you will be destroyed. Also when an enemy torpedo hits you you will be destroyed. The score will always be reset to 0 when you have been destroyed and the game will start over and over again...like I said only for the fun of it.
You can use the cursor keys to maneuver the ship and the space key to fire torpedos and that's it...as you can see...really simple :)
If you are interested in the game you can find the source code over at github.

For those of you that are also interested in jpro (running JavaFX apps in the browser), the latest version of jpro makes it possible to also run JavaFX apps that use the Canvas node!!! Oh yeah!!!

UPDATE:
Well after the last weekend the game now looks a bit more advanced and therefor I've created a new little video that shows the current version...here you go...



Well that's it for today...so keep coding...

Friday, February 2, 2018

Friday Fun LIX - Parallel Coordinates Chart

Aloha from Singapore one more time,

Today I have a chart for you which was a bit tricky to implement. It's a so called parallel coordinates chart and to be honest it doesn't look really fancy at a glance but it is really neat.
If you have no idea what it looks like here is a little image that show one...



First it looks like some kind of simple line chart but it's not. With this chart one can compare objects in a nice way. So let's assume you would like to compare cars and you would not only to compare one property of the cars like horsepower but a set of properties (e.g. cylinder, horsepower, acceleration, weight, consumption, etc.) and the whole comparison should be in one chart.
In this case the parallel coordinates chart ist perfect. Here is a little screenshot of my implementation that uses this example...



In this chart each line represents one car (e.g. the blue line represents my Smart Roadster Coupé and the purple line represents the Bugatti Veyron...a fair comparison right ;) ).
Now the interesting part about that chart is that it makes it easy to find similarities between cars or that you can figure out trends easily.
There are tons of possibilities on how to extend this chart but because I do not have the time for that I've just added two things that I've found very nice:

  • Dragging axes
  • Filter specific lines

So you can imagine that the order of the categories has a big impact on the expressiveness of the chart and therefor it is possible to drag a category by dragging the header of a category to another position...



Here I've simply moved some categories around to show the effect of the different category order.
The filtering of specific lines (cars in this example) works similar. Here you simply click close to one axis and drag down and you will see that a little rectangle will be drawn that selects the lines in the range of the rectangle.
If you release the mouse button it will show you something similar like follows...



As soon as you select some lines all other "unselected" lines will be drawn in light gray (configurable) and the selected lines will be drawn in blue (configurable). In addition the names of the selected lines will be shown on the left side. 
Once you click again somewhere the selection will be removed again.
In principle that's it and I hope it might be useful for someone. As always I have no usage for it at all :)
The chart is part of my JavaFX charts library where the current version is 1.0.5 and that you can found here:

Source at github

Binaries at bintray or Maven Central

And if you would like to see it in action, here is a short screen video that I've recorded...



That's it for today, so enjoy Carnival and don't forget...keep coding... ;)

Friday, December 15, 2017

Friday Fun LIV - Path Gradient

Aloha,

I've always thought about how to implement a path gradient. Meaning to say a gradient that follows a path. First of all keep in mind that this kind of gradient is not used very often but sometimes it can create some really nice effects.
I've mainly saw the effect in circular components like the fitness gauge on the Apple Watch...


The color of each bar changes along the bar as you can see on the image. For this specific problem I've created the ConicalGradient in the past which works nicely for circular components but what about this...



If you would like to fill the path above with a gradient from blue over green and yellow to red you will see that it won't work with linear gradients. You can either fill it horizontally or vertically but both times the gradient won't follow the path itself. So here are two examples...


To fill it with a gradient along the path you need to split the path into small segments and fill each segment with a linear gradient along the line.
If you go with this approach you can achieve something like follows...


As you can see here it works nicely but that was not that easy to realize. The most important part of this little fun project was taking a closer look to the goodies that are already in the JDK. Especially the Java2D package contains a lot of nice stuff.
So my idea was to use this kind of path gradient in the JavaFX canvas node and lucky me the Java2D api is quite close to the JavaFX canvas api.
I won't go through the code because it's simply to much but let me explain the steps that are needed to achieve that result...

  • Split the path into it's elements (MoveTo, LineTo, QuadCurveTo, BezierCurveTo, Close etc.)
  • Split each element into single lines
  • Stroke each single line with the right part of the complete gradient
Like already mentioned above a lot of the functionality is already in the JDK but unfortunately it sometimes is hidden in private classes that are not accessible from the outside. So the solution for this problem was to fork all parts that I needed from the Apache Harmony project (the stuff Android is based on). So in principle I've forked the all classes from the Java2D packages that are related to bounds, shapes and transforms.
In the classes above I've removed all 3D related things and completely switched to doubles instead of floats.
I've also added several other classes and added functionality to some of the classes. One problem was for example that in the JDK there was no code to split lines into "sub-lines" which means I had to add this kind of things.
I've also renamed some classes to be more compatible to the JavaFX canvas. So the CubicCurve now is a BezierCurve etc.
In the end I've needed a path class that holds all elements and a lookup mechanism for the gradient.
Long story short with my current implementation the code to produce the path gradient will look like follows...


GradientLookup gradientLookup = new GradientLookup();
gradientLookup.setStops(new Stop(0.0, Color.BLUE),
                        new Stop(0.25, Color.LIME),
                        new Stop(0.5, Color.YELLOW),
                        new Stop(0.75, Color.ORANGE),
                        new Stop(1.0, Color.RED));

Path path = new Path();
path.moveTo(91, 36);
path.lineTo(182, 124);
path.bezierCurveTo(248, 191, 92, 214, 92, 214);
path.bezierCurveTo(-26, 248, 200, 323, 200, 323);
path.bezierCurveTo(303, 355, 383, 141, 383, 141);


double lineWidth = 20;


Canvas            canvas = new Canvas(400, 400);
GraphicsContext2D ctx    = canvas.getGraphicsContext2D();
PathGradient.strokePathWithGradient(ctx, path, gradientLookup, lineWidth, StrokeLineCap.ROUND);


So as you can see I've tried to keep the api as close to the JavaFX canvas api as possible but instead of drawing the path directly on the canvas context you first create the path object, define a gradient lookup which contains the list of stops and colors you need for the gradient and define width for the stroked line.

That's already neat but it could even be better because in the Path class you will find a SVGParser and with this you can directly use a SVG path string from an SVG file.
As an example here is the SVG file of the path on the above image...


<?xml version="1.0" standalone="no"?>

<!-- Generator: Adobe Fireworks CS6, Export SVG Extension by Aaron Beall (http://fireworks.abeall.com) . Version: 0.6.1  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="Untitled-Page%201" viewBox="0 0 500 500" style="background-color:#ffffff00" 
    version="1.1"xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"
    x="0px" y="0px" width="500px" height="500px">
    <path d="M 91 36 L 182 124 C 248 191 92 214 92 214 C -26 248 200 323 200 323 C 303 355 383 141 383 141 " stroke="#000000" stroke-width="1" fill="none"/>
</svg>


And with the the mentioned parser the code above could also be written like follows...

Path path = new Path();
path.appendSVGPath("M 91 36 L 182 124 C 248 191 92 214 92 214 " +
                   "C -26 248 200 323 200 323 C 303 355 383 141 383 141");

double lineWidth = 20;

Canvas canvas       = new Canvas(400, 400);
GraphicsContext ctx = canvas.getGraphicsContext2D();

PathGradient.strokePathWithGradient(ctx, path, gradientLookup, lineWidth, StrokeLineCap.ROUND);

To me that looks quite ok :)
As always I do not really have any use case yet so the whole thing is not tested for all possible use cases but at least it will give you an idea what is possible :)

And also as always the code is available on github.

Well that's it for today...I hope it was somehow interesting...keep coding... :)

Friday, April 19, 2013

Validate it...

Hi there,
It's already some time ago when I released my last blog post but I was busy with presentation preparation, trainings, preparing stuff for my upcoming JavaFX related podcast etc.
I was playing around with validation using css styles and so far that is an easy way to do some validation. But I in the Java Swing days I used the GlasPane to draw validation icons on top of invalid or valid controls. This approach was not always useful but I liked it because I could use one set of validation icons and validate all kinds of controls. So I was asking myself how I could implement this behavior in JavaFX. 
I decided to go with the Canvas node because it has a translucent background by default and enables me to draw whatever I like by only using one node on the scene graph. The only disadvantage was that the Canvas node is like an image means it won't resize automatically but you have to take care about size by yourself.
Well the solution to this problem could be extending Canvas and implement the autosizing behavior or encapsulate the Canvas node into another node which could be resized automatically and react on the new size by using an InvalidationListener to the resizable control. I decided to encapsulate the Canvas node in a Region because it's lightweight and supports resizing. 
The implementation is more a proof of concept than a ready to go solution but it should be good enough to play around with it. It only takes two classes, the
  • ValidationPane
  • Validator
The ValidationPane is simply a Region which encapsulates a Canvas node. To use the ValidationPane one simply has to add the nodes that should get the validation overlays by using one of the following methods
  • add(Node node)
  • add(Pos position, Node node)
  • addAll(Node... nodes)
  • addAll(Pos position, Node... nodes)
Here is a short example that shows you how to add a TextField to the ValidationPane

TextField textField = new TextField();

ValidationPane validationPane = new ValidationPane();
validationPane.add(Pos.TOP_LEFT, textField);

As you could see it is possible to configure the position of the validation icon (the default position is Pos.TOP_LEFT).

There are five different states that one could use for validation
  • Validator.State.VALID
  • Validator.State.INVALID
  • Validator.State.INFO
  • Validator.State.OPTIONAL
  • Validator.State.CLEAR
To set the validation state of a node you simply have to call the setState() method on the validation pane, for the example above this would look like follows

validationPane.setState(textField, Validator.State.INVALID);

If you set the validation state to Validator.State.VALID the validation icon will fade out after 1500 ms to keep the interface clean. 
If the node is invalid the validation icon will stay visible as long as it is in the invalid state.
On the following screenshot you could see three different states (Validator.State.CLEAR has no indicator).


You could see all three available indicators on the image above (invalid, valid and info). 
The idea was to use the validation not only for textfields (which is most of the times the standard use case) but for example also for complete layout containers like a HBox, GridPane etc.
Therefor it works on the JavaFX Node instead of Control. I did not make very indeep tests with it and cannot guarantee that it works in any case but like I said it's more a proof of concept than a ready to go solution.
To use it you simply have to wrap your existing root pane in an additional StackPane and put the ValidationPane on top by adding it at the last node to the StackPane. Because the ValidationPane is transparent to mouse events it won't catch events and should be "invisible" to your application. The following image should try to give you an idea...



It was fun to create and very similar to the Swing GlasPane approach and proofed that even if JavaFX is based on a SceneGraph using nodes for visualization one could easy adopt a bitmap based approach by using the Canvas node.

If you are interested in the source code, please find it here.

ATTENTION: I'm using lambdas in the code which might not work in every IDE !!!


UPDATE:
During the last JavaFX training course at Canoo in Basel one of the attendees pointed me to a useful feature for the validation pane. If you think about nodes that are invalid and are not visible. These nodes should not show their validation icon right...so I've added this behavior to the ValidationPane. So if you would like to take a look, feel free to get the code from BitBucket. I've also updated the demo to show the new behavior.


That's it for today so keep coding...

Friday, June 1, 2012

Dead bitmaps could be beautiful... Part III

Let's continue the canvas fun with JavaFX 2.2. You know already that you could use the ImagePattern class to create patterns and use them to fill shapes in JavaFX 2.2. Well would it not be nice to have a tool to create patterns too ?
Of course it would be but why reinventing the wheel again if there is a nice tool already ???!!! I talk about Patternizer which is a really nice tool to create stripe based HTML5 canvas patterns online.


Ok, that means we have a tool that creates stripe based patterns on the web...and how could we use those patterns in JavaFX 2.2 ???
Well in Patternizer one could create a pattern and get the code that could then be used in combination with the patternizer javascript to draw the pattern in HTML5 Canvas. The code that will be created by Patternizer looks like this...


Fortunately the creator of Patternizer has put the code on Github where i forked it and ported it to JavaFX. I put the code into two classes
  • Stripe
  • Pattern
The Stripe class represents the definition of the Patternizer stripes and the Pattern class defines a set of Stripes with a given background color.
To make the usage as easy as possible I've created a little conversion method that takes the code created by Patternizer and creates a Pattern object from it. This means you could create your pattern online with Patternizer, create the javascript code, copy the code and paste it as string to the static method 

pattern = Pattern.getFromPatternizerString(PATTERNIZER_CODE_STRING);

and you are good to go and use this pattern as a fill pattern by calling

shape.setFill(pattern.getImagePattern(shape.getLayoutBounds()));

and that's it...
As an example I've created the pattern that you see on the screenshots and converted the given Patternizer code like this...


private static final Pattern PATTERN = Pattern.getFromPatternizerString("{\n" +
        "stripes : [ \n" +
        "    {\n" +
        "        color: '#ffed0d',\n" +
        "        rotation: 200,\n" +
        "        opacity: 72,\n" +
        "        mode: 'plaid',\n" +
        "        width: 2,\n" +
        "        gap: 98,\n" +
        "        offset: 16\n" +
        "    },\n" +
        "    {\n" +
        "        color: '#550000',\n" +
        "        rotation: 200,\n" +
        "        opacity: 43,\n" +
        "        mode: 'plaid',\n" +
        "        width: 30,\n" +
        "        gap: 70,\n" +
        "        offset: 80\n" +
        "    },\n" +
        "    {\n" +
        "        color: '#080070',\n" +
        "        rotation: 200,\n" +
        "        opacity: 50,\n" +
        "        mode: 'plaid',\n" +
        "        width: 10,\n" +
        "        gap: 10,\n" +
        "        offset: 0\n" +
        "    }\n" +
        "],\n" +
        "bg : '#ffffff'\n" +
        "}");

When using this PATTERN as fill style for a shape you will get something like this...


Nice isn't it...? 
For those of you that don't like the Copy-Paste thingy you could create the same pattern also in code like this...

private static final Pattern PATTERN = Pattern.Builder.create()
    .backgroundColor(Color.web("#ffffff"))
    .stripes(new Stripe[]{
        Stripe.Builder.create()
                      .color(Color.web("#ffed0d"))
                      .rotation(200)
                      .opacity(72)
                      .mode(Stripe.Mode.PLAID)
                      .width(2)
                      .gap(98)
                      .offset(16)
                      .build(),
        Stripe.Builder.create()
                      .color(Color.web("#550000"))
                      .rotation(200)
                      .opacity(43)
                      .mode(Stripe.Mode.PLAID)
                      .width(30)
                      .gap(70)
                      .offset(80)
                      .build(),
        Stripe.Builder.create()
                      .color(Color.web("#080070"))
                      .rotation(200)
                      .opacity(50)
                      .mode(Stripe.Mode.PLAID)
                      .width(10)
                      .gap(10)
                      .offset(0)
                      .build()
    }).build();

If you created a nice pattern by playing around with these parameters in JavaFX and would like to use this pattern also on your website with patternizer.js you simply could call the getAsPatternizerString() method in the Pattern class which will give you the same output that the Pattenizer page does.

And here are the source files as plain java files:


To make it a little bit more easy to play with these things I've added some patterns in the PatternizerFX.java file so that you take a look at it.

Finally I've also created a little YouTube video that shows how easy it is to use.

Thanx to Matthew Lein and Dave Johnson which created Patternizer.

 So enjoy JavaFX and keep coding...

Tuesday, September 13, 2011

FxgConverter 2.0

To get nice graphics from a drawing program into java code i use Adobe Fireworks capability to export Adobe fxg files which i convert into Java2d code.
Because my old fxg converter was not the most beautiful coded piece of software i always knew that someday in the future i would have to recreate it.
Long story short...it's done...


This is the new fxg converter...




As you can see it looks very similar to the old version and i only changed the available options.
In the background i now use a complete new parser/translator combi written in Groovy. 
This new parser/translator combi is able to convert fxg code to 


The GWT code might still have some issues because i never used GWT. So if you encounter problems with the GWT code, please let me know so that i can fix it.


The idea behind the converter is that you could create your graphics in a drawing program like Adobe Fireworks or Adobe Illustrator and export the graphics to an Adobe fxg file. If you drag this file to the fxg converter it will show you a preview of the drawing for example like this...




Now you could select the language/dialect to which the converter should convert the graphics code and press convert.
During the conversion (which could take some time dependend on the image size) the converter looks like this...




And after the conversion is finished you will find the file that contains the converted code on your desktop.


Java2D:
The java file is in principle a custom component incl. resizing logic that you directly use in a ui editor like matisse in Netbeans. The Java component uses the converted graphics in the form of java BufferedImage objects. Each layer of the original drawing will be a BufferedImage with the name of the layer. In addition to the java file the converter will also export a file named JavaShadow.java. This file contains methods to create drop- and innershadows and will only be used if you uncomment the lines in the component code.


JavaFX:
The javafx file is a javafx component that uses the converted graphics in the form of javafx Group objects. Each layer of the original drawing will be a javafx Group object with the name of the layer. In addition to the component file the converter will also export a file that uses the component so that you could directly see how you could implement the new javafx component in your code.


HTML5 Canvas:
The javascript file contains a canvas component that uses the converted graphics  in the form of context objects of <canvas> elements. In addition to the javascript file the converter will also export a html file that uses the canvas component so that you could see how you could implement the canvas component in your html page.


GWT:
The gwt file contains in principle the same code as the HTML5 Canvas code with just a few differences. You should be able to directly use the created file in your gwt project. Like i said before, if you encounter problems, please let me know.


UPDATE 1:
Since today (thursday, 15th of september) the FxgConverter2 also supports exports to GroovyFX which is in principle a groovier version of the JavaFX code.


UPDATE 2:
Since friday, 16th of september the FxgConverter2 also supports exports to Android devices. It will create a custom view that contains the image and will be instantiated by an Activity.


Geertjan Wielenga from the Netbeans team at Oracle is also working on a plugin of the converter. Check out his progress here...


You could find the new FXG Converter 2 here on this blog on the right side...


Please keep in mind that the new converter only supports FXG 2.0 (it will also convert FXG 1.0 but you'll find problems with gradients).


That's it for today...so keep coding...



Tuesday, April 19, 2011

BiLinearGradient in HTML5 canvas...

This is just a short one for all HTML5 canvas lovers...
Because it was not a big deal and might be usefull for one or the other i created also a javascript version of the bilinear gradient paint that one could use in HTML5 canvas. To make it possible i added one class that represents a color in the way that one could get the rgba values from a given color and a class that represents the bilinear gradient paint itself.
The result looks like this...


click here to see it live...
To see it live you just have to click the link below the image. Here is a small example on how to use the BiLinearGradient in JavaScript:


function init()
{


 

}

You have to place the above script in your html page <head> tag. If you don't know how to do that just take a look at the page sourcecode of the linked page below the image.


Here are the two files you need to create the bilinear color interpolation.


    RGBAColor.js


    BiLinearGradient.js


Enjoy coding...



Friday, April 1, 2011

SteelSeries JavaScript edition

Here we go again and it's again time for some canvas...
Those of you who followed this blog know that i started to port some of the components of the steelseries java library to html5 canvas. Because i'm not a javascript coder i had no idea how to build a library from these components and so i started playing around, trying this and that...
Finally i found a way that looks ok to me (but i might be wrong) and today i could present you the first version of the javascript version of the steelseries library (it only contains the Radial and RadialBargraph right now).

I tried to implement most of the features of the java version but right now there are still some feature missing.
Here is a list of the features that are supported by the javascript version:

GaugeType:

  • TYPE1
  • TYPE2
  • TYPE3
  • TYPE4


PointerType:

  • TYPE1
  • TYPE2
  • TYPE3
  • TYPE4
  • TYPE5
  • TYPE6
  • TYPE7
  • TYPE8

FrameDesign:

  • BLACK_METAL
  • METAL
  • SHINY_METAL
  • BRASS
  • STEEL
  • CHROME
  • GOLD


BackgroundColor:

  • DARK_GRAY
  • SATIN_GRAY
  • LIGHT_GRAY        
  • WHITE
  • BLACK
  • BEIGE
  • BROWN
  • RED
  • GREEN
  • BLUE


LcdColor:
  • BEIGE
  • BLUE
  • ORANGE
  • RED
  • YELLOW
  • WHITE
  • GRAY
  • BLACK
  • GREEN
  • BLUE2
  • BLUE_BLACK
  • BLUE_DARKBLUE
  • BLUE_GRAY
  • STANDARD
  • BLUE_BLUE
  • REDDARKRED


LedColor:
  • RED_LED
  • GREEN_LED
  • BLUE_LED
  • ORANGE_LED
  • YELLOW_LED
  • CYAN_LED
  • MAGENTA_LED


Color:
  • RED
  • GREEN
  • BLUE
  • ORANGE
  • YELLOW
  • CYAN        
  • MAGENTA
  • WHITE
  • GRAY
  • BLACK
  • RAITH
  • GREEN_LCD
  • JUG_GREEN


The Radial component also supports sections and areas. So there's no track right now (but it will come).

PREPARATION:
To make use of the library you have to add two files to your html page:

  • tween.js
  • steelseries.js

So a typical html5 page header will look like this...

e.g.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>Test</title>
    <script type='text/javascript' src='js/tween.js'></script>
    <script type='text/javascript' src='js/steelseries.js'></script>
...

USAGE:
To use the library you need to add a <canvas> tag for each gauge to the <body> of the page.

e.g.
...
<body onload='init()'>
    <canvas id='canvas1' width='200' height='200'>
        No canvas in your browser...sorry...
    </canvas>
    <canvas id='canvas2' width='200' height='200'></canvas>
<canvas id='canvas3' width='200' height='200'></canvas>
</body>
...
Now we only have to add the init() method in the <head> of the page, where we create the canvas components. !!! OLD VERSION !!!
function init()
{
  // Define some sections
  var sections = Array(steelseries.Section(0, 25, 'rgba(0, 0, 220, 0.3)'),
                       steelseries.Section(25, 50, 'rgba(0, 220, 0, 0.3)'), 
                       steelseries.Section(50, 75, 'rgba(220, 220, 0, 0.3)'));
  
  // Define one area
  var areas = Array(steelseries.Section(75, 100, 'rgba(220, 0, 0, 0.3)'));
            
  // Create one radial gauge
  var radial1 = new steelseries.Radial(
                    'canvas1',                              // the canvas element
                    steelseries.GaugeType.TYPE4,            // type of gauge
                    200,                                    // size of gauge
                    0,                                      // minimum value
                    100,                                    // maximum value
                    50,                                     // threshold
                    sections,                               // sections
                    areas,                                  // areas
                    'Test',                                 // title string
                    'Unit',                                 // unit string
                    steelseries.FrameDesign.METAL,          // frame design
                    steelseries.BackgroundColor.DARK_GRAY,  // background color
                    steelseries.PointerType.TYPE8,          // pointer type
                    steelseries.ColorDef.RED,               // pointer color
                    steelseries.LcdColor.STANDARD,          // lcd color
                    true,                                   // lcd visible
                    steelseries.LedColor.RED_LED,           // led color
                    true,                                   // led visible
                    false);                                 // play audio
  
  // Create a second radial gauge
  var radial2 = new steelseries.Radial(
                    'canvas2', 
                    steelseries.GaugeType.TYPE2, 
                    200, 
                    0, 
                    50, 
                    40, 
                    Array(steelseries.Section(0, 40, 'rgba(0, 255, 0, 0.3)')),
                    Array(steelseries.Section(40, 50, 'rgba(255, 0, 0, 0.5)')), 
                    'Test', 
                    'Unit', 
                    steelseries.FrameDesign.CHROME, 
                    steelseries.BackgroundColor.LIGHT_GRAY, 
                    steelseries.PointerType.TYPE2, 
                    steelseries.ColorDef.BLUE, 
                    steelseries.LcdColor.BLUE2, 
                    true, 
                    steelseries.LedColor.BLUE_LED, 
                    true, 
                    false);

  // Create a radial bargraph gauge
  var radial3 = new steelseries.RadialBargraph(
                    'canvas3',                               // the canvas element
                    steelseries.GaugeType.TYPE3,             // type of gauge
                    200,                                     // size of gauge
                    0,                                       // minimum value
                    100,                                     // maximum value
                    50,                                      // threshold
                    null,                                    // sections (not supported)
                    "Title",                                 // title string
                    "Unit",                                  // unit string
                    steelseries.FrameDesign.BLACK_METAL,     // frame design
                    steelseries.BackgroundColor.LIGHT_GRAY,  // background color 
                    steelseries.ColorDef.YELLOW,             // color of the bargraph led's
                    steelseries.LcdColor.YELLOW,             // lcd color
                    true,                                    // lcd visible
                    steelseries.LedColor.YELLOW_LED,         // led color
                    true);                                   // led visible

  // Let's set some values...
  radial1.setValueAnimated(70);
  radial2.setValueAnimated(41);
  radial3.setValueAnimated(70);
}

As you can see the drawback of the current design are the long constructors. I'm still not sure how to make these nicer but i'm working on that...


UPDATE:
Thanx to Andres Almiray who pointed me in the right direction i modified the constructor of the Radial and RadialBargraph component in the way that it now takes a hash as a set of parameters. This means you don't have to put in all the default parameters anymore which makes the initialization of the components look like this...
!!! NEW VERSION !!!


function init()
{
  // Define some sections
  var sections = Array(steelseries.Section(0, 25, 'rgba(0, 0, 220, 0.3)'),
                       steelseries.Section(25, 50, 'rgba(0, 220, 0, 0.3)'), 
                       steelseries.Section(50, 75, 'rgba(220, 220, 0, 0.3)'));
  
  // Define one area
  var areas = Array(steelseries.Section(75, 100, 'rgba(220, 0, 0, 0.3)'));
            
  // Create one radial gauge
  var radial1 = new steelseries.Radial(
                    'canvas1', {
                    section: sections,                      
                    area: areas,                            
                    titleString: 'Test',                    
                    unitString: 'Unit',                     
                    pointerType: steelseries.PointerType.TYPE8
                    });                               

// Create a second radial gauge
  var radial2 = new steelseries.Radial(
                    'canvas2', {
                    gaugeType: steelseries.GaugeType.TYPE2,                     
                    maxValue: 50, 
                    threshold: 40, 
                    section: Array(steelseries.Section(0,40,'rgba(0,255,0,0.3)')),
                    area: Array(steelseries.Section(40,50,'rgba(255,0,0,0.5)')), 
                    titleString: 'Test', 
                    unitString: 'Unit', 
                    frameDesign: steelseries.FrameDesign.CHROME, 
                    backgroundColor: steelseries.BackgroundColor.LIGHT_GRAY, 
                    pointerType: steelseries.PointerType.TYPE2, 
                    pointerColor: steelseries.ColorDef.BLUE, 
                    lcdColor: steelseries.LcdColor.BLUE2,                     
                    ledColor: steelseries.LedColor.BLUE_LED, 
                    });

  // Create a radial bargraph gauge
  var radial3 = new steelseries.RadialBargraph(
                    'canvas3', {
                    gaugeType: steelseries.GaugeType.TYPE3,
                    titleString: "Title",                                
                    unitString: "Unit",          
                    frameDesign: steelseries.FrameDesign.BLACK_METAL,
                    backgroundColor: steelseries.BackgroundColor.LIGHT_GRAY,
                    valueColor: steelseries.ColorDef.YELLOW,
                    lcdColor: steelseries.LcdColor.YELLOW,
                    ledColor: steelseries.LedColor.YELLOW_LED,
                    });                                   

  // Let's set some values...
  radial1.setValueAnimated(70);
  radial2.setValueAnimated(41);
  radial3.setValueAnimated(70);
}


Guess that looks much better than before... :-)




If you put all these things together in one html page you should see something like this...




If you are to lazy to play around you might want to click here to see it in action...


There are two versions of the library available right now, the uncompressed (101 kb) and compressed (61 kb) version. You could download the version clicking on one of the following links:


    uncompressed version:    steelseries.js


    compressed version:       steelseries-min.js


    animation library:           tween.js


Keep in mind that this project is work in progress and things might change in the future...


Enjoy the upcoming weekend and keep coding...