如何在extjs的饼图中给标签和图例赋予不同的字段

时间:2013-05-30 09:30:53

标签: extjs extjs4.1 sencha-architect extjs4.2

有人能告诉我如何在extjs的饼图中为标签和图例提供不同的字段吗?我有一个商店有两个名称,价值的字段。我想在标题中的图例和值字段中显示名称字段。现在我得到了labe1和legend的相同值。

由于

4 个答案:

答案 0 :(得分:2)

配置您的派系列的label属性,如下所示:

label: {
    // name of the model field to use as legend
    field: 'name'
    ,renderer: function(value, label, storeItem) {
        // storeItem is your model, so return the value you want as label
        return storeItem.get('value');
    }
}

编辑:

之前的代码仅适用于自Ext 4.2以来。要在4.1中使用它,您必须覆盖Ext.chart.series.Pie#onPlaceLabel()方法来替换行:

    label.setAttributes({
        text: format(storeItem.get(field[index]))
    }, true);

使用这些,来自Ext4.2代码:

    label.setAttributes({
        text: format(storeItem.get(field), label, storeItem, item, i, display, animate, index)
    }, true);

编辑2:如何覆盖Ext 4.1

在Ext 4中覆盖类的语法与用于扩展的类相同,只是您使用override而不是extend。与任何其他类一样,override类被命名。为了加载覆盖,您必须要求它,就像普通类一样(如果您不使用Ext Loader,那么您必须将该文件包含在脚本标记中。

现在,这里的代码将使值渲染器的工作方式与Ext4.2相同:

// Again, you're free to chose the class name, just ensure the Loader can find the file
// (and don't forget to require it!)
Ext.define('MyApp.Ext.char.series.Pie', {
    override: 'Ext.chart.series.Pie'

    ,onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
        var me = this,
            chart = me.chart,
            resizing = chart.resizing,
            config = me.label,
            format = config.renderer,
            field = [].concat(config.field),
            centerX = me.centerX,
            centerY = me.centerY,
            middle = item.middle,
            opt = {
                x: middle.x,
                y: middle.y
            },
            x = middle.x - centerX,
            y = middle.y - centerY,
            from = {},
            rho = 1,
            theta = Math.atan2(y, x || 1),
            dg = theta * 180 / Math.PI,
            prevDg;

        opt.hidden = false;

        if (this.__excludes && this.__excludes[i]) {
            opt.hidden = true;
        }

        function fixAngle(a) {
            if (a < 0) {
                a += 360;
            }
            return a % 360;
        }

        label.setAttributes({
            // Removed:
            // text: format(storeItem.get(field[index]))
            // Added:
            text: format(storeItem.get(config.field), label, storeItem, item, i, display, animate, index)
        }, true);

        switch (display) {
            case 'outside':
                rho = Math.sqrt(x * x + y * y) * 2;
                //update positions
                opt.x = rho * Math.cos(theta) + centerX;
                opt.y = rho * Math.sin(theta) + centerY;
                break;

            case 'rotate':
                dg = fixAngle(dg);
                dg = (dg > 90 && dg < 270) ? dg + 180: dg;

                prevDg = label.attr.rotation.degrees;
                if (prevDg != null && Math.abs(prevDg - dg) > 180 * 0.5) {
                    if (dg > prevDg) {
                        dg -= 360;
                    } else {
                        dg += 360;
                    }
                    dg = dg % 360;
                } else {
                    dg = fixAngle(dg);
                }
                //update rotation angle
                opt.rotate = {
                    degrees: dg,
                    x: opt.x,
                    y: opt.y
                };
                break;

            default:
                break;
        }
        //ensure the object has zero translation
        opt.translate = {
            x: 0, y: 0
        };
        if (animate && !resizing && (display != 'rotate' || prevDg != null)) {
            me.onAnimate(label, {
                to: opt
            });
        } else {
            label.setAttributes(opt, true);
        }
        label._from = from;
    }
});

如您所见,我必须复制粘贴整个方法代码。我不喜欢这样,因为这使我们在未来的版本中很大程度上暴露了任何代码更改,但是没有其他可能的方法来改变我所针对的代码。

在现实生活中,为了防范这种风险,我会添加版本检查并在Ext版本大于4.1时发出警告:

// Using a function instead of a raw object, in order to run some code at the time of class definition
Ext.define('MyApp.Ext.char.series.Pie', function() {
    if (Ext.getVersion().isGreaterThanOrEqual('4.2')) {
        Ext.Logger.warn('This override is rendered useless since Ext4.2');
        return {};
    } else {
        return {
            override: 'Ext.chart.series.Pie'

            ,onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
                var me = this,
                    chart = me.chart,
                    resizing = chart.resizing,
                    config = me.label,
                    format = config.renderer,
                    field = [].concat(config.field),
                    centerX = me.centerX,
                    centerY = me.centerY,
                    middle = item.middle,
                    opt = {
                        x: middle.x,
                        y: middle.y
                    },
                    x = middle.x - centerX,
                    y = middle.y - centerY,
                    from = {},
                    rho = 1,
                    theta = Math.atan2(y, x || 1),
                    dg = theta * 180 / Math.PI,
                    prevDg;

                opt.hidden = false;

                if (this.__excludes && this.__excludes[i]) {
                    opt.hidden = true;
                }

                function fixAngle(a) {
                    if (a < 0) {
                        a += 360;
                    }
                    return a % 360;
                }

                label.setAttributes({
                    // Removed:
                    // text: format(storeItem.get(field[index]))
                    // Added:
                    text: format(storeItem.get(config.field), label, storeItem, item, i, display, animate, index)
                }, true);

                switch (display) {
                    case 'outside':
                        rho = Math.sqrt(x * x + y * y) * 2;
                        //update positions
                        opt.x = rho * Math.cos(theta) + centerX;
                        opt.y = rho * Math.sin(theta) + centerY;
                        break;

                    case 'rotate':
                        dg = fixAngle(dg);
                        dg = (dg > 90 && dg < 270) ? dg + 180: dg;

                        prevDg = label.attr.rotation.degrees;
                        if (prevDg != null && Math.abs(prevDg - dg) > 180 * 0.5) {
                            if (dg > prevDg) {
                                dg -= 360;
                            } else {
                                dg += 360;
                            }
                            dg = dg % 360;
                        } else {
                            dg = fixAngle(dg);
                        }
                        //update rotation angle
                        opt.rotate = {
                            degrees: dg,
                            x: opt.x,
                            y: opt.y
                        };
                        break;

                    default:
                        break;
                }
                //ensure the object has zero translation
                opt.translate = {
                    x: 0, y: 0
                };
                if (animate && !resizing && (display != 'rotate' || prevDg != null)) {
                    me.onAnimate(label, {
                        to: opt
                    });
                } else {
                    label.setAttributes(opt, true);
                }
                label._from = from;
            }
        };
    }
}()); // the define function must be executed manually with overrides (this is documented in the API)

答案 1 :(得分:1)

I don't know whether it is against the copyright law or not 

我不负责任。但会起作用

step 1 

open  touch/src/chart/series/pie.js file 

step 2
 add one property to this file  (like legendLabel:null,)
step 3 
 Edit method  provideLegendInfo: function (target) . and change 
 labelField = this.getLabelField(), to
 labelField = this.getLegendLabel()
step 4<br>
Add new property to series you create in your file to show pie chart


    series: [
                    {
                        type: 'pie',
                        legendLabel :'name',
                        xField: 'value',                        
                        labelField: 'value',

}]


promote  this answer if you find this is helpful 
thank u

答案 2 :(得分:1)

这适用于Ext 4.0

new Ext.chart.Chart({
  store: store, 
  series: [{
    type: 'pie',
    field: 'value',
    label: {
        field: 'name',
        renderer: function(value){
            Ext.each(store.data.items, function(item){
                if(item.data.name == value) {
                    value = item.data.value;
                }
            });
            return value;
        }
    }
  }],
  ... 

存储数据如下:

[{"name":"series1","value":5},{"name":"series2","value":7}]

答案 3 :(得分:0)

我可以使用rendererFn(sprite)分别在图例和PIE上显示两个不同的标签。在这里,您不需要编辑JS文件。

在“系列”部分的“标签”类别下,使用“字段”显示“图例”文本,在渲染器功能中使用值作为输出,将值返回到饼图。

系列:[{             类型:'馅饼',             字段:'价值',             甜甜圈:25,
            showInLegend:true,

        label: {
            field: 'name',
            renderer: {rendererFn},
            display: 'inside'
        }
        ,renderer: function(sprite, config, rendererData, index) {
            return { text: {rendererFn}(window.dataJSON[index]['value']) };
        }
}]

这就足够了。