PDA

View Full Version : [FIXED-EXTJSIV-219] Chart Y-Axis label issues



margozzi
18 Mar 2011, 11:58 AM
The labels for the Y-Axis do not render nicely when the chart is vertically small. In the images, you will see that values drop out as the chart gets smaller. One would expect either all of the labels or none of the labels to appear since they are all the same font and should have the same height.
25231
25232
25233
25234
Note another curious issue on the last image. The scale goes to 120, even though my configuration sets minimum to 0 and maximum to 100.


axes: [{
type: 'Numeric',
minimum: 0,
maximum: 100,
position: 'left',
fields: ['V1'],
title: 'CPU Load',
grid: {
odd: {
opacity: 1,
fill: '#ddd',
stroke: '#bbb',
'stroke-width': 0.5
}
},
label: {
renderer: Ext.util.Format.numberRenderer('0,0'),
font: '12px Arial'
}
}

bbraun
18 Mar 2011, 8:04 PM
I think the calculation of minimum and maximum values for numeric axes needs some serious work. The calcEnds and snapEnds functions seem to reassing minimum and maximum values, enev if they had been assigned explicity in the config. For a Y axis minimum, I'm getting an axis starting at -30 even if I try to start with a minimum of -21. I think it might be because snapEnds is trying to start with a number having one significatn figure? I could not quite understand the code there.

example:

function showPlot() {
var chart = new Ext.chart.Chart({
width: 800,
height: 600,
animate: true,
store: store1,
renderTo: 'plotDiv',
shadow: false,
theme: 'Category1',
legend: {
position: 'right',
boxStroke: 'none'
},
axes: [
{
type: 'Numeric',
position: 'left',
title: 'pctChangeTitle',
fields: ['pctChange'],
scale: 'linear',
majorUnit: 2.0,
minimum: -21.0,
maximum: 10.0,
adjustMinimumByMajorUnit: false,
snapToUnits : false,
label: {renderer: Ext.util.Format.numberRenderer('0,0.00') }
},
{
type: 'Numeric',
position: 'bottom',
fields: ['change'],
title: 'changeTitle',
width: 5,
majorUnit : 1.0,
minimum: -5.0, //broken?
maximum: 5.0,
adjustMinimumByMajorUnit: false,
adjustMaximumByMajorUnit: false,
snapToUnits : true,
label: {renderer: Ext.util.Format.numberRenderer('0,0.00') }
}
],
series: [{
type: 'line',
axis: ['left','bottom'],
xField: 'change',
yField: 'pctChange',
markerCfg: {
type: 'circle',
radius: 5,
fill: '#0f0',
'stroke-width': 2,
size: 20
}
}]
});
Am I doing it wrong? I think that if I specify axis min and max, then the drawing code should not override them.

On a related note, I think that snapEnds also is making an assumption that the axis length will be a multiple of the major division. This may not be the case. For example, I might want an axis from 0 to 105, with a major division of 20. In this case, the axis will extend a bit beyond the last major division.

Thanks, I'm new to ExtJS and I think it is amazing!

philogb
25 Mar 2011, 1:54 PM
Hi,

Thanks for the report.

The images that have the y-axis labels hidden are actually correct. Not all labels have a centered baseline -in particular the top one hasn't because we want it to stay within the area of the chart.

For each label, if the label overlaps with some previously rendered label then it is not rendered. It's normal then that some labels are shown and some hidden.

As for the minimum and maximum values this has been fixed for the next release.

Thanks again for the report,

margozzi
25 Mar 2011, 2:45 PM
See the attached image for more feedback. Basically, I understand your position, but think there is room for improvement as well.

I would rather you loose the 0 and or the 100 rather than have gaps in the axis labels.

Does the inclusion of an X-Axis make for a better rendering?

25353

philogb
25 Mar 2011, 2:54 PM
Would it be possible to provide me the complete code of your example so I can test it here? We've changed the way collision detection is done for the labels of a chart and this might solve the `80` problem.

Thanks,

margozzi
25 Mar 2011, 3:09 PM
JS source:

Ext.require('Ext.chart.*');
Ext.require('Ext.layout.container.Fit');

Ext.onReady(function() {
var index = 0;

Ext.regModel('LongSeries', {
fields: [
{ name: 'IdentifierList', type: 'string' },
{ name: 'TotalCount', type: 'int' },
{ name: 'BaseTime', type: 'int' }
],
hasMany: 'TimedLongs'
});

Ext.regModel('TimedLongs', {
fields: [
{
name: 'T',
convert: function(value, record) {
return index++;
}
},
{ name: 'V1', type: 'int' },
{ name: 'V2', type: 'int' },
{ name: 'V3', type: 'int' },
{ name: 'V4', type: 'int' },
{ name: 'V5', type: 'int' },
{ name: 'V6', type: 'int' },
{ name: 'V7', type: 'int' },
{ name: 'V8', type: 'int' }
],
belongsTo: 'LongSeries'
});

var cpusProxy = {
type: 'ajax',
url : '/dxi/rest/CpuStats?filter=Time(GT)0',
reader: {
type: 'xml',
record : 'TimedLongs'
}
}

var aveProxy = {
type: 'ajax',
url : '/dxi/rest/CpuAverageStats?filter=Time(GT)0',
reader: {
type: 'xml',
record : 'TimedLongs'
}
}

var store = new Ext.data.Store({
model: 'TimedLongs',
proxy: cpusProxy
});

var win = Ext.create('Ext.Window', {
x: 100,
y: 100,
width: 600,
height: 400,
title: 'CPU utilization',
renderTo: Ext.getBody(),
layout: {
type: 'hbox',
align: 'stretch'
},
items: {
xtype: 'chart',
flex: 1,
store: store,
insetPadding: 30,
legend: {
position: 'bottom'
},
axes: [{
type: 'Numeric',
minimum: 0,
maximum: 100,
position: 'left',
fields: ['V1'],
title: 'CPU Load',
grid: {
odd: {
opacity: 1,
fill: '#ddd',
stroke: '#bbb',
'stroke-width': 0.5
}
},
label: {
renderer: Ext.util.Format.numberRenderer('0,0'),
font: '12px Arial'
}
}
/*
,{
type: 'Time',
position: 'bottom',
fields: ['T'],
groupBy: 'hour,second',
title: false,
dateFormat: 'g:i:s',
step: [Ext.Date.SECOND, 1],
}
*/
],
series: [{
title: 'CPU 1',
type: 'line',
showMarkers: false,
showLegend: true,
axis: 'left',
xField: 'T',
yField: 'V1',
tips: {
trackMouse: true,
width: 100,
height: 28,
renderer: function(storeItem, item) {
this.setTitle( 'cpu 1: ' + storeItem.get('V1') + '%');
}
},
style: {'stroke-width': 2}
},{
title: 'CPU 2',
type: 'line',
showMarkers: false,
showLegend: true,
axis: 'left',
xField: 'T',
yField: 'V2',
tips: {
trackMouse: true,
width: 100,
height: 28,
renderer: function(storeItem, item) {
this.setTitle( 'cpu 2: ' + storeItem.get('V2') + '%');
}
},
style: {'stroke-width': 2}
},{
title: 'CPU 3',
type: 'line',
showMarkers: false,
showLegend: true,
axis: 'left',
xField: 'T',
yField: 'V3',
tips: {
trackMouse: true,
width: 100,
height: 28,
renderer: function(storeItem, item) {
this.setTitle( 'cpu 3: ' + storeItem.get('V3') + '%');
}
},
style: {'stroke-width': 2}
},{
title: 'CPU 4',
type: 'line',
showMarkers: false,
showLegend: true,
axis: 'left',
xField: 'T',
yField: 'V4',
tips: {
trackMouse: true,
width: 100,
height: 28,
renderer: function(storeItem, item) {
this.setTitle( 'cpu 4: ' + storeItem.get('V4') + '%');
}
},
style: {'stroke-width': 2}
}]
},
tbar: [ {
text : 'Pause',
scope: this,
handler : function(btn, ev) {
Ext.TaskMgr.stop(task);
}
}, '-', {
text : 'Resume',
multiSelect: true,
scope: this,
handler : function(btn, ev) {
Ext.TaskMgr.start(task);
}
}, '-', {
xtype: 'combo',
fieldLabel: 'Select',
labelWidth: 45,
width: 150,
editable: false,
forceSelection: true,
queryMode: 'local',
store: new Ext.data.ArrayStore({
fields: [
'value',
'displayText'
],
data: [['CpuStats', 'All CPUs'], ['CpuAverageStats', 'Averaged']]
}),
valueField: 'value',
displayField: 'displayText',
listeners:{
'select': function(){
if( this.getValue() )
store.setProxy( this.getValue() == 'CpuStats' ? cpusProxy : aveProxy );
}
}
}]
});

win.show();

var task = {
run: function(){
index = 0;
store.load();
},
interval: 2000 //2 second
}
Ext.TaskMgr.start(task);
});

HTML source:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>CPU Utilization</title>
<link rel="stylesheet" type="text/css" href="../ext40/resources/css/ext-all.css" />
<style>

.x-panel {
margin: 20px;
}
h1 {
font-size: large;
margin: 10px;
}
body {
padding: 30px;
}
</style>
<script type="text/javascript" src="../ext40/bootstrap.js"></script>
<script type="text/javascript" src="Charts.js"></script>
</head>
<body id="docbody">
<h1>CPU Utilization</h1>
<div style="margin: 10px;">
Displaying CPU utilization with mouse over and click interaction. <a href="Charts.js">View Source</a>
</div>
</body>
</html>

sample XML data from back end:

<LongSeries><IndentifierList>CPU1,CPU2,CPU3,CPU4,CPU5</IndentifierList><TotalCount>30</TotalCount><BaseTime>1301094198777</BaseTime><TimedLongs><T>0</T><V1>64</V1><V2>95</V2><V3>23</V3><V4>33</V4><V5>39</V5></TimedLongs><TimedLongs><T>2000</T><V1>4</V1><V2>94</V2><V3>22</V3><V4>45</V4><V5>15</V5></TimedLongs><TimedLongs><T>4000</T><V1>93</V1><V2>66</V2><V3>91</V3><V4>29</V4><V5>2</V5></TimedLongs><TimedLongs><T>6000</T><V1>81</V1><V2>73</V2><V3>27</V3><V4>81</V4><V5>21</V5></TimedLongs><TimedLongs><T>8000</T><V1>57</V1><V2>2</V2><V3>71</V3><V4>71</V4><V5>42</V5></TimedLongs><TimedLongs><T>10000</T><V1>46</V1><V2>70</V2><V3>18</V3><V4>55</V4><V5>34</V5></TimedLongs><TimedLongs><T>12000</T><V1>29</V1><V2>84</V2><V3>49</V3><V4>39</V4><V5>78</V5></TimedLongs><TimedLongs><T>14000</T><V1>8</V1><V2>62</V2><V3>94</V3><V4>90</V4><V5>18</V5></TimedLongs><TimedLongs><T>16000</T><V1>67</V1><V2>70</V2><V3>41</V3><V4>11</V4><V5>12</V5></TimedLongs><TimedLongs><T>18000</T><V1>14</V1><V2>80</V2><V3>15</V3><V4>62</V4><V5>45</V5></TimedLongs><TimedLongs><T>20000</T><V1>54</V1><V2>28</V2><V3>31</V3><V4>44</V4><V5>30</V5></TimedLongs><TimedLongs><T>22000</T><V1>11</V1><V2>62</V2><V3>66</V3><V4>24</V4><V5>84</V5></TimedLongs><TimedLongs><T>24000</T><V1>55</V1><V2>50</V2><V3>28</V3><V4>74</V4><V5>30</V5></TimedLongs><TimedLongs><T>26000</T><V1>70</V1><V2>26</V2><V3>83</V3><V4>92</V4><V5>78</V5></TimedLongs><TimedLongs><T>28000</T><V1>71</V1><V2>29</V2><V3>31</V3><V4>18</V4><V5>56</V5></TimedLongs><TimedLongs><T>30000</T><V1>90</V1><V2>19</V2><V3>13</V3><V4>42</V4><V5>82</V5></TimedLongs><TimedLongs><T>34003</T><V1>22</V1><V2>48</V2><V3>24</V3><V4>97</V4><V5>86</V5></TimedLongs><TimedLongs><T>36005</T><V1>59</V1><V2>41</V2><V3>21</V3><V4>21</V4><V5>64</V5></TimedLongs><TimedLongs><T>38008</T><V1>22</V1><V2>43</V2><V3>42</V3><V4>24</V4><V5>35</V5></TimedLongs><TimedLongs><T>40011</T><V1>25</V1><V2>33</V2><V3>79</V3><V4>14</V4><V5>89</V5></TimedLongs><TimedLongs><T>42014</T><V1>4</V1><V2>13</V2><V3>68</V3><V4>20</V4><V5>45</V5></TimedLongs><TimedLongs><T>44001</T><V1>39</V1><V2>42</V2><V3>75</V3><V4>19</V4><V5>98</V5></TimedLongs><TimedLongs><T>46004</T><V1>58</V1><V2>79</V2><V3>46</V3><V4>75</V4><V5>37</V5></TimedLongs><TimedLongs><T>48006</T><V1>45</V1><V2>72</V2><V3>78</V3><V4>84</V4><V5>32</V5></TimedLongs><TimedLongs><T>50007</T><V1>28</V1><V2>53</V2><V3>30</V3><V4>80</V4><V5>46</V5></TimedLongs><TimedLongs><T>52008</T><V1>84</V1><V2>64</V2><V3>31</V3><V4>69</V4><V5>66</V5></TimedLongs><TimedLongs><T>54009</T><V1>82</V1><V2>60</V2><V3>64</V3><V4>1</V4><V5>76</V5></TimedLongs><TimedLongs><T>56010</T><V1>50</V1><V2>56</V2><V3>40</V3><V4>39</V4><V5>97</V5></TimedLongs><TimedLongs><T>58011</T><V1>9</V1><V2>18</V2><V3>35</V3><V4>99</V4><V5>11</V5></TimedLongs><TimedLongs><T>60012</T><V1>9</V1><V2>97</V2><V3>80</V3><V4>64</V4><V5>50</V5></TimedLongs></LongSeries>