Ext JSのシャレオツな設定を外部定義でテーマ化し、幸せなチャートライフを送れる(かもしれない)方法

前回の続き書いていきます :)

前回

前回のエントリーでイケてないチャートコンポーネントをシャレオツな感じにカスタマイズしました。

今回はそのシャレオツな見た目の設定をテーマ化してみたいと思います。

チャートのテーマ設定方法

既に読み込まれているテーマであれば、チャートコンポーネントに themeプロパティを設定するだけでOKです

Ext.define('App.view.charts.B', {
    extend  : 'Ext.chart.Chart',
    xtype   : 'chart-b',
    width   : 500,
    height  : 200,
    animate : true,
    theme   : 'xxxxx', ← テーマ名を設定
    store   : 'LineStore',
    ...

たったこれだけでOKです!:)
で、肝心のテーマ作成ですが

もう少しちゃんとしたやり方があると思うんですが、取り急ぎで実装しちゃってます

Themeクラス

ファイル構成等の説明は省略します :(
下記JavaSciprtファイル場所:app/chart/theme/FlatLine.js

Ext.define('App.chart.theme.FlatLine', {
    singleton: true,
    configure: function() {
        Ext.chart.theme.FlatLine = Ext.extend(Ext.chart.theme.Base, {
            constructor: function(config) {
                Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
                    // ここにスタイル設定を書いていきます
                }, config));
            }
        });
    }
});

上記コードの次の部分 Ext.chart.theme.FlatLine = となっている Ext.chart.theme. 以降の文字列がテーマ名として設定される部分になります。

では、スタイル設定を追記していきます。
ちょっとコードが大量になるので、一部省略して書きます。

最後に全文コード載せるので、めんどくさい人はそちらを見てください

axis の設定を行います。 設定している内容は、ラインの太さと色の設定です。

・・・
Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
    axis: {
        'stroke'        : '#f0f0f0',
        'stroke-width'  : 1,
    },
}, config));
・・・

axis のラベル部分とタイトル部分のスタイル設定を行います。
axis の表示位置によって異なるスタイル設定を行う事が可能です。

今回はタイトルは利用していないので、タイトル部分の設定は行っておらず、ラベルに関しては取り急ぎ、BottomとLeftの設定のみ行っています。設定内容については、フォントの設定とフォントの色をへこうしています。

・・・
Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
    axis: {
        'stroke'        : '#f0f0f0',
        'stroke-width'  : 1,
    },
    axisLabelTop    : {},
    axisLabelRight  : {},
    axisLabelBottom : {
        'rotate': {
            'degrees': 315
        },
        'font': '11px メイリオ',
        'fill': '#666'
    },
    axisLabelLeft   : {
        'font': '10px メイリオ',
        'fill': '#666'
    },
    axisTitleTop    : {},
    axisTitleRight  : {},
    axisTitleBottom : {},
    axisTitleLeft   : {},
}, config));
・・・

seriesおよびseriesLabelは、プロパティ名のままで series のスタイルと series のラベルのスタイル設定を行っています。ここで、seriesに設定しているスタイルはラインの幅、seriesLabelはフォントとフォント色を指定しています。

・・・
Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
    axis: {
        'stroke'        : '#f0f0f0',
        'stroke-width'  : 1,
    },
    axisLabelTop    : {},
    axisLabelRight  : {},
    axisLabelBottom : {
        'rotate': {
            'degrees': 315
        },
        'font': '11px メイリオ',
        'fill': '#666'
    },
    axisLabelLeft   : {
        'font': '10px メイリオ',
        'fill': '#666'
    },
    axisTitleTop    : {},
    axisTitleRight  : {},
    axisTitleBottom : {},
    axisTitleLeft   : {},
    series: {
        'stroke-width': 3
    },
    seriesLabel: {
        'font': '11px メイリオ',
        'fill': '#666'
    },
}, config));
・・・

markerの設定を行います。(LineチャートのLine上に表示される点の部分) Lineチャートのタイプだったり枠線、marker自体のサイズ設定などを行っています。

・・・
Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
    axis: {
        'stroke'        : '#f0f0f0',
        'stroke-width'  : 1,
    },
    axisLabelTop    : {},
    axisLabelRight  : {},
    axisLabelBottom : {
        'rotate': {
            'degrees': 315
        },
        'font': '11px メイリオ',
        'fill': '#666'
    },
    axisLabelLeft   : {
        'font': '10px メイリオ',
        'fill': '#666'
    },
    axisTitleTop    : {},
    axisTitleRight  : {},
    axisTitleBottom : {},
    axisTitleLeft   : {},
    series: {
        'stroke-width': 3
    },
    seriesLabel: {
        'font': '11px メイリオ',
        'fill': '#666'
    },
    marker: {
        'type'          : 'circle',
        'radius'        : 6,
        'stroke'        : '#FFF',
        'stroke-width'  : 1.5
    },
}, config));
・・・

最後に、seriesに対して複数の series が設定された場合(Lineチャートであれば複数のラインが表示されるような場合)に、それぞれの色やタイプを設定することが出来る seriesThemes(ライン)と markerThemes(マーカー)があります。

・・・
Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
    axis: {
        'stroke'        : '#f0f0f0',
        'stroke-width'  : 1,
    },
    axisLabelTop    : {},
    axisLabelRight  : {},
    axisLabelBottom : {
        'rotate': {
            'degrees': 315
        },
        'font': '11px メイリオ',
        'fill': '#666'
    },
    axisLabelLeft   : {
        'font': '10px メイリオ',
        'fill': '#666'
    },
    axisTitleTop    : {},
    axisTitleRight  : {},
    axisTitleBottom : {},
    axisTitleLeft   : {},
    series: {
        'stroke-width': 3
    },
    seriesLabel: {
        'font': '11px メイリオ',
        'fill': '#666'
    },
    marker: {
        'type'          : 'circle',
        'radius'        : 6,
        'stroke'        : '#FFF',
        'stroke-width'  : 1.5
    },
    seriesThemes: [{
        fill: "#115fa6"
    }, {
        fill: "#94ae0a"
    }],
    markerThemes: [{
        type: 'circle' 
    }, {
        type: 'circle' 
    }]
}, config));
・・・

これで一通り完了です。
このThemeファイルの最終的なコードが下記になります。


最終的なFlatLineクラス

Ext.define('App.chart.theme.FlatLine', {
    singleton: true,
    configure: function() {
        Ext.chart.theme.FlatLine = Ext.extend(Ext.chart.theme.Base, {
            constructor: function(config) {
                Ext.chart.theme.Base.prototype.constructor.call(this, Ext.apply({
                    axis: {
                        'stroke'        : '#f0f0f0',
                        'stroke-width'  : 1,
                    },
                    axisLabelTop    : {},
                    axisLabelRight  : {},
                    axisLabelBottom : {
                        'rotate': {
                            'degrees': 315
                        },
                        'font': '11px メイリオ',
                        'fill': '#666'
                    },
                    axisLabelLeft   : {
                        'font': '10px メイリオ',
                        'fill': '#666'
                    },
                    axisTitleTop    : {},
                    axisTitleRight  : {},
                    axisTitleBottom : {},
                    axisTitleLeft   : {},
                    series: {
                        'stroke-width': 3
                    },
                    seriesLabel: {
                        'font': '11px メイリオ',
                        'fill': '#666'
                    },
                    marker: {
                        'type'          : 'circle',
                        'radius'        : 6,
                        'stroke'        : '#FFF',
                        'stroke-width'  : 1.5
                    },
                    seriesThemes: [{
                        fill: "#115fa6"
                    }, {
                        fill: "#94ae0a"
                    }],
                    markerThemes: [{
                        type: 'circle' 
                    }, {
                        type: 'circle' 
                    }]
                }, config));
            }
        });
    }
});

で、これを使ってLineチャートのコンポーネントの設定を行ってみましょう。 前回のチャートコンポーネントを少しだけ弄って、テーマを適用してみたのが次のコード

Ext.define('App.view.charts.B', {

    extend: 'Ext.chart.Chart',

    requires: [
        'App.chart.theme.FlatLine'
    ],

    xtype   : 'chart-b',
    width   : 500,
    height  : 200,
    animate : true,
    theme   : 'FlatLine',
    store   : 'LineStore',
    shadow  : false,

    initComponent: function() {
        var me = this;

        Ext.applyIf(me, {
            axes: [{
                type        : 'Numeric',
                position    : 'left',
                fields      : ['data1', 'data2'],
                grid        : true,
                minimum     : 0,
                gridColor   : '#f0f0f0'
            },{
                type        : 'Category',
                position    : 'bottom',
                fields      : ['name'],
                grid        : false
            }],
            series: [{
                type        : 'line',
                smooth      : true,
                axis        : 'left',
                xField      : 'name',
                yField      : 'data1'
            }, {
                type        : 'line',
                smooth      : true,
                fill        : true,
                style       : {
                    'fillOpacity': 0.2
                },
                axis        : 'left',
                xField      : 'name',
                yField      : 'data2'
            }]
        });

        me.callParent(arguments);
    },

    constructor: function() {
        App.chart.theme.FlatLine.configure();
        this.callParent(arguments);
    }

});

今回のチャートでは正直しなくても問題ないですが、initComponentのタイミングでプロパティの定義を行うように変更しています。(コンポーネント生成するタイミングでごにょりたい時に便利なので)
あとは、表示するシリーズ追加したりちょこちょこ変更してますが、前のままでも問題ないです。

肝心のテーマの使い方は

  • テーマ用のクラスをrequiresに定義する
    • 別の箇所で読み込んでいるなら必要無いです
  • チャートコンポーネントのthemeプロパティにテーマ名を設定
  • チャートコンポーネントのconstructorメソッドを追加
    • その中でThemeクラスのconfigureメソッドを実行

だけでOKです。
これを表示してみると・・・

こんな感じで表示されます。
Themeクラスの読み込み方法はもう少し利口なやり方がありそうな気がしますが、とりあえずは所定位置にThemeクラス設置して上記の設定だけ行えば見た目の変更が出来ちゃいます!

axisのgridColorなど、一部プロパティがTheme側で設定出来ない気がするので、極力テーマ側に寄せれるようにもう少しちゃんとソース追います :(