PrimeFaces - customise Date Chart

phoenix7360 picture phoenix7360 · Jan 10, 2013 · Viewed 13.1k times · Source

I am using PrimeFaces 3.4.1 to plot time chart (Date on x-axis, int value on y-axis).

At the moment I have something like that:

xhtml:

<p:lineChart id="timeChart" value="#{myGraphBean.model}" legendPosition="e" title="Time Chart" minY="0" maxY="25" style="height:300px"/>

Java bean:

private final static int MAX_VALUE = 20;
private final static int NUMBER_OF_POINTS = 20;
private final static DateFormat dateFormat = new SimpleDateFormat("dd-MM-yy");

private void createLinearModel() {
    model = new CartesianChartModel();
    Calendar day = Calendar.getInstance();
    day.set(Calendar.HOUR_OF_DAY, 0);
    day.set(Calendar.MINUTE, 0);
    day.set(Calendar.SECOND, 0);
    day.set(Calendar.MILLISECOND, 0);
    LineChartSeries series = new LineChartSeries();
    series.setLabel("My series");
    for (int i = 0; i < NUMBER_OF_POINTS; i++) {
        series.set(dateFormat.format(day.getTime()), getRandomValue());
        day.add(Calendar.DAY_OF_MONTH, 1);
    }
    model.addSeries(series);
}

private int getRandomValue() {
    return rand.nextInt(MAX_VALUE);
}

So my bean just creates some random int value for each day. (My application produces actual data points, this is just a dummy example)

In my application, I am generating data over a long time, for example 6 months. With the way I am doing things now, I get horrible graphs like that:

Bad graph

What I would like to do:

I'd like to be able to keep my data point but only display a tick, let's say every month.

I have tried to change the tick on the x-axis following a few other posts (ex1, ex2) but I couldn't get it work.

Using the primefaces extender, I tried to use things like tickInterval: '1 month', setting the min attributes but nothing worked. In most of the case it would just break the graph

Questions:

  1. In the jqPlot doc, it says "Note, although jqPlot will parse most any human readable date, it is safest to use javascript time stamps when possible. Also, it is best to specify a date and time and not just a date alone. This is due to inconsistent browser handling of local time vs. UTC with bare dates." In my graph bean, shall I populate the series using a formatted date (String) following the javascript time stamp ("yyyy-MM-dd h:mma") or using a java.util.Date directly?

  2. How can I change the x-axis tick (for let's say 1 month), having a marker only every month, but still have the graph going through all the day points (i.e. I don't want to average my the points over the month)?

Answer

perissf picture perissf · Jan 11, 2013

In Java, fill your LineChartSeries objects with times in milliseconds using Date#getTime().

On the facelets side, download from jqPlot site and import the following jqPlot plugins:

<h:outputScript name="Javascript/jqplot.canvasAxisTickRenderer.js" />
<h:outputScript name="Javascript/jqplot.canvasAxisTickRenderer.min.js" />
<h:outputScript name="Javascript/jqplot.dateAxisRenderer.js" />
<h:outputScript name="Javascript/jqplot.dateAxisRenderer.min.js" />

And use this js extender for p:lineChart component:

function chartExtender() {
    this.cfg.axes = {
        xaxis : {
            renderer : $.jqplot.DateAxisRenderer, 
            rendererOptions : {
                tickRenderer:$.jqplot.CanvasAxisTickRenderer
            },
            tickOptions : { 
                fontSize:'10pt',
                fontFamily:'Tahoma', 
                angle:-40
            }
        },
        yaxis : {
            rendererOptions : {
                tickRenderer:$.jqplot.CanvasAxisTickRenderer
            },
            tickOptions: {
                fontSize:'10pt', 
                fontFamily:'Tahoma', 
                angle:30
            }
        }               
    };
    this.cfg.axes.xaxis.ticks = this.cfg.categories;
}

Useful links:

http://forum.primefaces.org/viewtopic.php?f=3&t=25289#p79916

http://forum.primefaces.org/viewtopic.php?f=3&t=23891&p=78637#p78637