[Ext JS 4] Extjs 图表 Legend(图例)的分行与分列显示

Extjs 中的Chart 的legend.

Legend, 翻译过来的意思是图例。

在Extjs 的Chart 中, 到底代表什么呢? 直接看这张图:

右边红色框起来的部分就是Legend 了。

在 Extjs Chart 的定义中, 可以通过配置 legend 的配置值(configs)来设置Legend 显示的位置和样式:

position 配置显示的位置:可以设置的值有 "top","bottom", "left", "right", or "float"。

其他还可以设置图例显示的文字、图的样式等等, 详细可以参见 Ext.chart.Legend 的参考文档。

具体的设置类似:

Legend 如何分列或者分行 -- 历程

不管居于什么位置,Extjs  Legend 默认的显示方式都是单行或是当列。(根据位置配置的差异)

查阅Legend 的参考文档的所有配置,属性和方法都找不到, 如何将Legend 可以分行或分列显示的方法。

倒是在 legendItem 的参考文档中,找到了 updatePosition( [relativeTo] )的方法。

Legend是整个图例, LegendItem 应该就是里面的每一项图例了。

于是产生了一种解法:

1. 是否可以在合适的时候, 设置legendItem 的位置

首先第一个问题, 什么是合适的时候? 是否可以在 afterRender 事件中,

但是实际测试发现, 在Chart 的afterRender 中, 图例并没有产生出来。 这个Form , Grid 的机制看上去不太一样。

没办法,只能先整一个按钮, 通过点击来看看这种解法是否可行。

1)  得到Chart 的legend

	var chart = Ext.getCmp("testChart");
	var legend = chart.legend;

我的Chart Id 是: testChart

2)  得到ChartItems

var legendItems = legend.items;

3)  循环以上数组,设置各Item 的位置, 位置是自己计算出来的(x,y 坐标)

legendItem.updatePosition({x:xPos,y:yPos});

位置的确是改变了。

到此, 问题并没有结束,

legend 上的Item 是可以进行点击的, 而且点击之后,相应的图是可以进行显示和隐藏的切换的。

使用以上方式, 发现点击之后, 又恢复原状了。

于是又产生了一种想法,

2. 是否可以给LegendItem 添加, click 事件, 在click 中重新计算位置并更新/

legendItem.on("click",function(){
	legendItem.updatePosition({x:xPos,y:yPos});
});

这样的写法是否繁杂不说, 会发现一个问题:

就是legendItem 必须要点两次以上才能触发上面的function.

而且Dubug 发现, 此时Legend item 有两个click 事件,一个是原生的,一个是后来加的。

这样的方式肯定会存在问题。

所以以上的方式只能宣告失败。

Legend分列或者分行

看来只能从Extjs 的源码层级考虑了。

Extjs Chart 的最底层的技术无非是 SVG, VML.

关于此的详细介绍可以参考:

[Web Chart系列之一]Web端图形绘制SVG,VML, HTML5 Canvas 技术比较

而Extjs 的Chart 又是基于raphael 框架之上。  关于raphael 的详细,可以参考官方网站:

http://raphaeljs.com/

思考的历程就统统省去,直接给出结论就是: 重写  Ext.chart.LegendItem 和 Ext.chart.Legend 的 updatePosition方法:

<!--Add by oscar999-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Author" CONTENT="oscar999">
<script>
</script>
</HEAD>

<BODY>

</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="../ext-all-debug.js"></script>
<link href="../resources/ext-theme-neptune/ext-theme-neptune-all.css" rel="stylesheet" type="text/css" />

<script>
Ext.chart.LegendItem.override({
    updateSpecPosition: function(positionTo) {
        var me = this,
            items = me.items,
            ln = items.length,
            i = 0,
            item;
		var posX = positionTo.x;
		var posY = positionTo.y;
        for (; i < ln; i++) {
            item = items[i];
            switch (item.type) {
                case ‘text‘:
                    item.setAttributes({
                        x: 20 + posX,
                        y: posY
                    }, true);
                    break;
                case ‘rect‘:
                    item.setAttributes({
                        translate: {
                            x: posX,
                            y: posY - 6
                        }
                    }, true);
                    break;
                default:
                    item.setAttributes({
                        translate: {
                            x: posX,
                            y: posY
                        }
                    }, true);
            }
        }
    }
});
Ext.chart.Legend.override({
 updatePosition: function() {
        var me = this,
            items = me.items,
            pos, i, l, bbox;

        if (me.isDisplayed()) {

            pos = me.calcPosition();

            me.x = pos.x;
            me.y = pos.y;

            //items[i].updatePosition({x:100,y:100});

            var posX = me.x;
            var posY = me.y;
            for (i = 0, l = items.length; i < l; i++) {
            	posX = me.x;
            	posY = me.y;
            	//items[i].updatePosition();
            	if(i%2>0)
            	{
            		posX += 80;
            	}

            	posY += parseInt(i/2)*30;

            	items[i].updateSpecPosition({x:posX,y:posY});
            }

            bbox = me.getBBox();

            if (isNaN(bbox.width) || isNaN(bbox.height)) {
                if (me.boxSprite) {
                    me.boxSprite.hide(true);
                }
            }
            else {
                if (!me.boxSprite) {
                    me.createBox();
                }

                me.boxSprite.setAttributes(bbox, true);
                me.boxSprite.show(true);
            }
        }
    }
});

</script>

<script>

Ext.onReady(function(){
	var store = Ext.create(‘Ext.data.JsonStore‘, {
        fields: [‘year‘, ‘comedy‘, ‘action‘, ‘drama‘, ‘thriller‘],
        data: [
                {year: 2005, comedy: 34000000, action: 23890000, drama: 18450000, thriller: 20060000},
                {year: 2006, comedy: 56703000, action: 38900000, drama: 12650000, thriller: 21000000},
                {year: 2007, comedy: 42100000, action: 50410000, drama: 25780000, thriller: 23040000},
                {year: 2008, comedy: 38910000, action: 56070000, drama: 24810000, thriller: 26940000}
              ]
    });

    var chart = Ext.create(‘Ext.chart.Chart‘,{
            id:‘testChart‘,
    		animate: true,
            shadow: true,
            store: store,
            legend: {
                //position: ‘right‘,
                //position:‘float‘,
                position: ‘bottom‘,
                boxStroke: ‘#FFF‘,
                legendCol:2,
                update:false
            },
            axes: [{
                type: ‘Numeric‘,
                position: ‘bottom‘,
                fields: [‘comedy‘, ‘action‘, ‘drama‘, ‘thriller‘],
                title: false,
                grid: true,
                label: {
                    renderer: function(v) {
                        return String(v).replace(/(.)00000$/, ‘.$1M‘);
                    }
                }
            }, {
                type: ‘Category‘,
                position: ‘left‘,
                fields: [‘year‘],
                title: false
            }],
            series: [{
                type: ‘bar‘,
                axis: ‘bottom‘,
                gutter: 80,
                xField: ‘year‘,
                yField: [‘comedy‘, ‘action‘, ‘drama‘, ‘thriller‘],
                stacked: true,
                tips: {
                    trackMouse: true,
                    width: 65,
                    height: 28,
                    renderer: function(storeItem, item) {
                        this.setTitle(String(item.value[1] / 1000000) + ‘M‘);
                    }
                }
            }]
        });

    var panel1 = Ext.create(‘widget.panel‘, {
        width: 800,
        height: 400,
        title: ‘Stacked Bar Chart - Movies by Genre‘,
        renderTo: Ext.getBody(),
        layout: ‘fit‘,
        tbar: [{
            text: ‘Save Chart‘,
            handler: function() {
                Ext.MessageBox.confirm(‘Confirm Download‘, ‘Would you like to download the chart as an image?‘, function(choice){
                    if(choice == ‘yes‘){
                        chart.save({
                            type: ‘image/png‘
                        });
                    }
                });
            }
        }],
        items: chart
    });
});

</script>
</head>
<body>
<div id="my-div"></div>
<div id="user-div" class="applicantItem" style="display:none"></div>
</body>
</html>

注意:

1. 以上并不是一个完整与完美的代码, 只是说明可以使用这种方式进行的POC的代码

2. 排列的位置, 需要自行去运算出来,多行, 还是多列?

效果与总结

最后,给出一下笔者实现的效果

当然, 如果LegendItem 比较少的话, 分行与分列并没有什么意义。

比较适用的场景是: legendItem 很多,超过20 甚至30, 大大影响了页面的感官。

不过实际开发中,这种状况应该比较少。

如果实在有这种状况, 就要从需求开始就的慎重考量了,尽量避免出现这种需求, 因为即使开发出来的, 针对如此多的Series , 速度自然快不了。

[Ext JS 4] Extjs 图表 Legend(图例)的分行与分列显示

时间: 2024-10-17 02:21:25

[Ext JS 4] Extjs 图表 Legend(图例)的分行与分列显示的相关文章

[Ext JS 4] Extjs 之 initComponent 和 constructor的区别

initComponent 和 constructor是什么 Extjs 提供的组件还是挺丰富的, 但是有时候需求更丰富. 当Extjs 原生的组件无法实现我们的要求的时候, 就需要扩展Extjs 的组件实现自制组件了. 除了这种使用状况, 有时候对于一些相同却有使用很多的配置, 可能像把它独立出来,单独设为一种组件供大家调用, 节省开发时间和提高代码重用度. initComponent 和 constructor 就是Extjs 提供用来实现继承和扩展的方式. Ext.define 实现扩展

[Ext JS 4] 实战之Load Mask(加载遮罩)的显示与隐藏

前言 Load Mask(遮罩)效果,就是在页面还没有完全显示出来之前, 加上一个转装转的效果. 类似: 添加这样的效果有两个好处: 1. 在页面没完全show出来之前, 把后面的页面给遮罩起来, 防止进行一些非法的操作. 2. 如果页面show出来的时间比较长的话, 可以暂时吸引用户的注意力(也就是提高 User Experience). 在Extjs 中, Ext js 的使用方式有多种. 你有可能会发现为什么有的状况下load mask 不出现?  且听下面一一道来... JsonStor

[Ext JS 4] 实战之Load Mask - 在Grid Reconfigure的使用状况

前言 关于 Extjs 的 load mask 的使用,可以参考: [Ext JS 4] 实战之Load Mask(加载遮罩)的显示与隐藏 一般而言,在如下情况下可能要使用grid 的 reconfigure功能: 1. 改变grid 的显示栏位 (增加或更换, 这和 hide , show 已经有的栏位不同) 2. 切换grid 的View 和 Edit 模式(这里面的内容就比较多了) 这里要讨论的问题是: 在 reconfigure 的时候, grid 是否可以有 load mask 的遮罩

【翻译】Ext JS 5的平板支持

原文:Ext JS 5 Tablet Support Ext JS已被公认为桌面Web应用程序的领先框架.自从平板开始在全球挑战PC的销售,无论是个人还是企业,电脑横向的应用已经产生急剧的变化.Sencha意识到了这种变化,并推出了包含新功能和进行优化了的Ext JS 5. Ext JS从Sencha Touch 2学到了一些新把戏.多年最好的移动Web应用程序框架经验的沉淀要应对现代平板电脑上的桌面显示,那是卓卓有余的.通过类系统.事件管理.窗口小部件和新的部署选项就可以了解到这些更新. 除了

Ext JS 6学习文档–第1章–ExtJS入门指南

Ext JS 入门指南 前言 本来我是打算自己写一个系列的 ExtJS 6 学习笔记的,因为 ExtJS 6 目前的中文学习资料还很少.google 搜索资料时找到了一本国外牛人写的关于 ExtJS 6 的电子书 [Ext JS 6 By Example].这份资料在 PACKT 上卖 35.99 刀的,当然了万能的 google 还是帮我下载到了 PDF 文档.大概看了一下,讲的很详细,例子也比较简单,容易理解,现我准备利用工作之余翻译这份文档,为自己学习加深理解,也希望能帮助更多的人学习.

&lt;ext JS&gt; EXTJS的安装、sencha Cmd的安装、EXTJS数据包等

一.EXT的安装 Ext JS SDK. 在右方选择EXTJS,在输入邮箱,选中接受,然后下载,通过邮件的方式发送下载链接. 二.EXTJS的类声明方式与实例化操作 EXTJS声明方法:Ext.define(); EXTJS实例化方法:Ext.create(); 三.组件 组件(component) 是对数据和方法的简单封装. 组件体系: 这种元素间的关系使得组件呈现层级关系.下图 展示了 ExtJS4.x 中组件间层级关系一种实例. 子组件通过容器的items加入到容器中,下面这个例子通过Ex

highcharts图表的图例legend怎么改变显示位置

一.将图例Legend放于图表右侧1.设置chart的marginRight属性值:chart: { marginRight: 120}2.设置legend图例属性值如下 legend: { align: 'right', //水平方向位置 verticalAlign: 'top', //垂直方向位置 x: 0, //距离x轴的距离 y: 100 //距离Y轴的距离} 3.效果图: 二.将图例放于图表左上角1.设置legend的属性legend: { align: 'left', //水平方向位

[Ext JS 4] 实战之Chart 坐标控制(单坐标,双坐标)

前言 在Extjs 中, 单一的 Column Chart 的展示效果如上. 定义的步骤如下: 1.  创建一个 Ext.chart.Chart 2. 创建两个坐标轴, axes 一个 Category 类型的横坐标用来显示日期 一个Numeric 类型的纵坐标用来显示数据 3. 配置显示的图 series 配置 column 类型的柱状图. 具体代码如下: <!-- Author : oscar999 Date : ALL RIGHTS RESERVED --> <!DOCTYPE h

运用 Ext JS 4 的 MVC 架构

http://www.open-open.com/lib/view/open1350386395227.html http://www.ibm.com/developerworks/cn/web/1210_wangzh_extjsmvc/index.html Ext JS 4 简介 Ext JS 4 目前是 Sencha 的产品,4.x 的正式版本号是 4.0.7.Ext JS 4 提供商业版本,但如果您的项目是开源的,则可以免费使用 Ext JS 4.Ext JS 的论坛目前非常活跃:Ext