图例模板 - 图表

时间:2013-07-30 18:30:21

标签: extjs sencha-touch sencha-touch-2 sencha-charts

我有这个模板(默认)

<span class="x-legend-item-marker {[values.disabled?'x-legend-inactive':'']}" style="background:{mark};"></span>{name}

产生这个:

enter image description here

我希望每个功能都具有相同的模板。但是,我还需要一个if子句。如果它的值为0,我不希望某个项目是“legendarize”。

这是完整的代码

{
xtype: 'container',
                title: 'Chart',
                iconCls: 'chart',
                itemId: 'chart_Tab',
                layout: {
                    type: 'fit'
                },
                items: [
                    {
                        xtype: 'polar',
                        itemId: 'pie',
                        colors: [
                            '#115fa6',
                            '#94ae0a',
                            '#a61120',
                            '#ff8809',
                            '#ffd13e',
                            '#a61187',
                            '#24ad9a',
                            '#7c7474',
                            '#a66111',
                            '#222222',
                            '#115ea6',
                            '#94cc0a',
                            '#b61120',
                            '#dd8809',
                            '#11d13e',
                            '#a68887',
                            '#94df9d',
                            '#7f74f4',
                            '#112341',
                            '#abcdef1'
                        ],
                        store: 'relativedata',
                        series: [
                            {
                                type: 'pie',
                                label: {
                                    textBaseline: 'middle',
                                    textAlign: 'center',
                                    font: '9px Helvetica'
                                },
                                labelField: 'strName',
                                labelOverflowPadding: 0,
                                xField: 'numValue'
                            }
                        ],
                        interactions: [
                            {
                                type: 'rotate'
                            }
                        ],
                        listeners: [
                            {
                                fn: function(element, eOpts) {
                                    var relStore = Ext.getStore('relativedata');
                                    var eleStore = Ext.getStore('element');
                                    var relModel;
                                    var eleModel;

                                    relStore.removeAll();

                                    //Convert to CO2 qty
                                    for(var i = 0; i< eleStore.getCount();i++)
                                    {
                                        eleModel = eleStore.getAt(i);
                                        relModel = Ext.create(APPNAME + '.model.RelativeElement');
                                        relModel.set('strName',eleModel.get('strName'));
                                        relModel.set('numValue', eleModel.get('numValue')*eleModel.getFactor());
                                        relStore.add(relModel);
                                    }

                                    relStore.sync();

                                    //Hide arrows-legend
                                    this._series[0]._label.attr.hidden=true;
                                },
                                event: 'painted'
                            }
                        ],
                        legend: {
                            xtype: 'legend',
                            docked: 'bottom',
                            itemId: 'pie_legend',
                            itemTpl: [
                                '<span class="x-legend-item-marker {[values.disabled?\'x-legend-inactive\':\'\']}" style="background:{mark};"></span>{name}'
                            ],
                            maxItemCache: 100,
                            store: 'element'
                        }
                    }
                ]
            }

我请求帮助,因为我对模板不太好。我不敢说我​​理解默认的一切。

1 个答案:

答案 0 :(得分:3)

我回来了!然而,没有人因此而称我为苗条的傻瓜......不幸的是!

因此,要回答您的初始问题,您需要的模板将如下所示:

// Configuration of the chart legend
legend: {
    // Finally, we can use the value field to customize our templates.
    itemTpl: [
        '<tpl if="value != 0">', // <= template condition
            '<span class="x-legend-item-marker {[values.disabled?\'x-legend-inactive\':\'\']}" style="background:{mark};"></span>{name}',
        '</tpl>'
    ]
    // ...
}

不幸的是,正如我在之前的评论中所说,快速调试程序检查显示此value变量或任何等效项在应用此模板时不可用。

现在我要给你一个详细的解释,说明我是如何克服这种烦恼的。在某种程度上,因为这是一个涉及到黑客行为,如果你决定应用它,你最好知道你正在做什么,部分原因是你通过见证钓鱼技术而不是通过给予正确的鱼来学习更多东西离开 - 在这种情况下,鱼无论如何都不能用于零售。而且在很大程度上,我必须承认,因为我喜欢抒情我已经投入精力的事情,而且已经很晚了,我对自我祝贺的防御变得有点弱......

因此,查看Ext.chart.Legend的代码显示,那里没有什么可做的,它只是Ext.dataview.Dataview的一个轻量级扩展。因此,它必须有一个与它绑定的商店,显然(并且不幸的是),它不是图表中提供数据的那个。

另一个明智的断点(在Legend的{​​{1}}方法中)显示此商店来自setStore,而在code of this class我们可以看到两件事:a专用图例商店为created in the constructorchart series implement a method to feed this storeprovideLegendInfo

我们正在接近我们的目标。我们需要做的是为图例库添加一个值字段,让我们的系列为该字段提供数据。太好了!

现在明智的做法是使用Ext代码的最小复制量来实现这些修改......但是在花费inconsiderate amount of time试图做到这一点之后没有运气,我只会疯狂地解决覆盖这两种方法,并给出一个大胆的警告来检查这些方法的代码是否随着Touch的下一个版本而改变:

Ext.chart.AbstractChart

有了这一点,让我们在没有为子孙后代进一步考虑的情况下走到这一步。

也就是说,首先我们向图例商店添加一个值字段:

if (Ext.getVersion().isGreaterThan('2.2.1')) {
    // Give yourself a big warning to check that the overridden methods' code
    // bellow has not changed (see further comments).
}

第二,我们使我们的图表系列提供该值。从您的代码中,我可以推断出您正在使用饼图,所以我只是为此提供代码,这只是为了说明......但是,如果你一直关注到这里,它应该是微不足道的为其他类型的系列实现它。无论如何,这是代码:

/**
 * Adds a value field to legend store.
 */
Ext.define(null, {
    override: 'Ext.chart.AbstractChart'
    // Berk, what a lot of code replication :( Let's just hope that this method's code
    // won't change in the future...
    ,constructor: function() {
        var me = this;
        me.itemListeners = {};
        me.surfaceMap = {};
        me.legendStore = new Ext.data.Store({
            storeId: this.getId() + '-legendStore',
            autoDestroy: true,
            fields: [
                'id', 'name', 'mark', 'disabled', 'series', 'index'
                // Adding my value field
                ,'value'
            ]
        });
        me.suspendLayout();

        // For whatever reason, AbstractChart doesn't want to call its superclass
        // (Ext.draw.Component) constructor and, by using callSuper, skips directly to
        // Ext.Container's one. So well... I respect, but I must do it old school since
        // callSuper would go to Ext.draw.Component from here.
        Ext.Container.prototype.constructor.apply(this, arguments);
        // me.callSuper(arguments);

        me.refreshLegendStore();
        me.getLegendStore().on('updaterecord', 'onUpdateLegendStore', me);
        me.resumeLayout();
    }
}, function() {
    // Post-create functions are not called for overrides in touch as they are 
    // in ExtJS? Hmm... That would have been the perfect place to issue a big
    //  warning in case the version has changed, but we'll live with it :(
});

让我们总结一下。我们有两个覆盖和一个自定义模板。我们希望我们现在就能完成。但这是我们得到的:

Empty serie without CSS

因此,/** * Overrides `provideLegendInfo` to add the value to the legend records. * * Here again, let us all cross our fingers very hard, hoping for Sencha's team to not decide * to add their own extra fields too soon... */ Ext.define(null, { override: 'Ext.chart.series.Pie' ,provideLegendInfo: function(target) { var store = this.getStore(); if (store) { var items = store.getData().items, labelField = this.getLabelField(), field = this.getField(), hidden = this.getHidden(); for (var i = 0; i < items.length; i++) { target.push({ name: labelField ? String(items[i].get(labelField)) : field + " " + i, mark: this.getStyleByIndex(i).fillStyle || this.getStyleByIndex(i).strokeStyle || 'black', disabled: hidden[i], series: this.getId(), index: i // Providing actual data value to the legend record ,value: items[i].get(field) }); } } } }); DataView标记周围添加了一些自己的标记。好吧,好吧......好吧......在这一点上,我已经厌倦了追踪Ext的内部,幸运的是(一次!),我设想了一个快速补丁。所以我毫不犹豫地把这个CSS规则扔进了:

itemTpl

最后我们完成了。我想我的思路和代码可能有点难以复制,所以让我给你一个definitive proof,这一切都有效。

在此演示中,有一个“度量标准4”,其值为0.

.x-legend-item:empty {
    display: none;
}

但你不会看到它。因为这就是所有这一切,不是吗?