グラフの軸を反転させたい
Highfacesでとあるランキングの折れ線グラフを作成する際、ランキングなのでy軸の最大値を0にする必要があります。ただ、HighChartsにはある「reversed」(軸を反転させるオプション)がHighfacesにはなかったので、カスタムタグを作成して「reversed」を指定できるようにします。
タグハンドラとコンポーネントを拡張する
以下のタグハンドラと、グラフとグラフの軸用のコンポーネントを拡張します。
このとき、「reversed」という属性を指定できるように、ChartAxisExクラスにアクセサを追記しています。
ChartHandler.java
public class ChartHandlerEx extends ChartHandler {
public ChartHandlerEx(ComponentConfig config) {
super(config);
}
}
ChartHandler.java
@FacesComponent("hogehoge.component.ChartEx")
public class ChartEx extends Chart {
}
ChartAxis.java
@FacesComponent("hogehoge.component.ChartAxisEx")
public class ChartAxisEx extends ChartAxis {
public Object getReversed() {
return Object.class.cast(this.getStateHelper().eval("reversed", null));
}
public void setReversed(Object value) {
this.getStateHelper().put("reversed", value);
}
}
レンダラを拡張する
「reversed」オプションを出力するように、ChartRendererクラスを拡張し、「encodeAxes」というメソッドに以下を追記します。
ChartRendererEx.java
@FacesRenderer(componentFamily = "org.highfaces.component", rendererType = "hogehoge.renderer,ChartRendererEx")
@ListenerFor(systemEventClass = PostAddToViewEvent.class)
public class ChartRendererEx extends ChartRenderer {
@Override
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
// 省略
}
private void encodeAxes(FacesContext context, Chart cv, JSONObject high) throws JSONException, IOException {
// 省略
if (axis.getReversed() != null) {
j.put("reversed", axis.getReversed());
}
}
taglib.xmlを作成する
src/main/resources/META-INFにtaglib.xmlを作成して、上記で拡張したクラスを指定します。
highfaces.taglib.xml
<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
version="2.0">
<namespace>http://hogehoge.jp/taglib</namespace>
<tag>
<tag-name>chartEx</tag-name>
<component>
<component-type>hogehoge.component.ChartEx</component-type>
<renderer-type>hogehoge.renderer.ChartRendererEx</renderer-type>
<handler-class>hogehoge.component.ChartHandlerEx</handler-class>
</component>
<attribute>
<description><![CDATA[Type of the charts, possible values are line, spline, area, column, bar and pie]]></description>
<name>type</name>
<required>true</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[List of HTML colors for the chart series. Defaults to "#2f7ed8,#0d233a,#8bbc21,#910000,#1aadce,#492970,#f28f43,#77a1e5,#c42525,#a6c96a".]]></description>
<name>colors</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[Datasource of the component, can be a Collection or Map type. Provide either a value, a model or chartseries as children declared in the xhtml file.]]></description>
<name>value</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[Datasource of the component, must implement the ChartModel interface. Provide either a value, a model or chartseries as children declared in the xhtml file.]]></description>
<name>model</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[ValueExpression of the currently selected Series.]]></description>
<name>selectedSeries</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[ValueExpression of the currently selected Point inside the selected Series. This corresponds to the category/value of the x axis.]]></description>
<name>selectedPoint</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[JavaScript to be executed on point selection.]]></description>
<name>onselect</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[Height of chart in px]]></description>
<name>height</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[Width of chart in px]]></description>
<name>width</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[Title for the chart]]></description>
<name>title</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[Credits text for the chart]]></description>
<name>credits</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[Zoom type text for the chart]]></description>
<name>zoomType</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[Sub Title for the chart]]></description>
<name>subTitle</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[Label for x-axis]]></description>
<name>xaxisLabel</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[Label for y-axis]]></description>
<name>yaxisLabel</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[Name of the request scoped variable used as iterator for value]]></description>
<name>var</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[Index of currently rendered item during iteration over the Collection in value-Attribute]]></description>
<name>rowIndexVar</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[ValueExpression of the value of a point, bar,... Only valid if used in combinatino with value.]]></description>
<name>point</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[ValueExpression of the tickLabel for a single point. Only valid if used in combinatino with value.]]></description>
<name>tickLabel</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[ID of rerender component for ajax actions]]></description>
<name>render</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[JavaScript function name for client side customization. All highcharts configuration options are available inside the function using 'this'.]]></description>
<name>extender</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[Whether to stack the values of each series on top of each other. Possible values are 'none', 'normal' or 'percent', defaulting to 'none'.]]></description>
<name>stacking</name>
<required>false</required>
<type>java.lang.String</type>
</attribute>
<attribute>
<description><![CDATA[If set, this is the time interval in seconds that the updateMethod will be called and series data will change.]]></description>
<name>updateInterval</name>
<required>false</required>
<type>java.lang.Integer</type>
</attribute>
<attribute>
<description><![CDATA[How many points should be always visible in the chart in liveUpdate mode ? Defaults to 20.]]></description>
<name>updateCapacity</name>
<required>false</required>
<type>java.lang.Integer</type>
</attribute>
<attribute>
<description><![CDATA[This method will be called via AJAX each time, the chart needs to update the visible data. Use it to change or add data to the displayed series.]]></description>
<name>updateMethod</name>
<required>false</required>
<type>javax.el.MethodExpression</type>
</attribute>
<attribute>
<description><![CDATA[JavaScript to be executed on mouse over event.]]></description>
<name>onmouseover</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[JavaScript to be executed on mouse over event.]]></description>
<name>onmouseoverpoint</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
</tag>
<tag>
<tag-name>chartAxisEx</tag-name>
<component>
<component-type>hogehoge.component.ChartAxisEx</component-type>
</component>
<attribute>
<description><![CDATA[Position of this axis. Possible values are n, w, s or e.]]></description>
<name>position</name>
<required>true</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[Angle in degrees if the tickLabel should be rotated. Defaults to 0.]]></description>
<name>tickAngle</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[Color of the gridline for this axis within the chart.]]></description>
<name>gridLineColor</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[Width of the gridline for this axis within the chart. Use 0 to not display a gridline.]]></description>
<name>gridLineWidth</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[Type of this axis. Possible values are linear, category and datetime, defaulting to linear.]]></description>
<name>type</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[Label-Style of this axis. Use CSS definition style to e.g. define a color.]]></description>
<name>style</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[Title of this axis.]]></description>
<name>title</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[Label-Format of this axis. To display e.g. mm use "{value} mm"]]></description>
<name>format</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[Minimum value for this axis]]></description>
<name>min</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[Maximum value for this axis]]></description>
<name>max</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
<attribute>
<description><![CDATA[Reversed for this axis]]></description>
<name>reversed</name>
<required>false</required>
<type>java.lang.Object</type>
</attribute>
</tag>
</facelet-taglib>
実際に使ってみる
カスタムタグができたので、「chartAxisEx」タグで「reversed」が指定できることを確認します。
hogehoge.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:hf="http://highfaces.org"
xmlns:ex="http://hogehoge.jp/taglib">
<h:head>
<title>hogehogeグラフ</title>
</h:head>
<h:body>
<ex:chartEx type="line" title="hogehogeグラフ">
<hf:chartSerie name="何かの順位"
value="#{hogehogeBean}"
var="rank" point="#{rank.rank}" tickLabel="#{rank.time}">
</hf:chartSerie>
<ex:chartAxisEx position="w" min="1" max="100" reversed="true"
title="" />
<ex:chartAxisEx position="s" title="" type="datetime"
format="{value:%Y.%m.%d}" />
</ex:chartEx>
</h:body>
</html>
完了
以上で、Highfacesを拡張して、グラフの軸が反転できるようになりました。