標籤:c style class blog code java
Sencha出品的ExtJs是一個非常優秀的前端架構,尤其是具有裡程碑意義的4.0的發布。4.0採用MVC架構和全新的class系統,並且提供了非常豐富的組件。但是,儘管ExtJS如此強大,仍有不盡人意的地方。比如,chart裡座標軸的刻度通常是均勻分布的,ExtJS的實現也是通過座標軸的最大值和最小值以及其他參數配置均勻的計算刻度。但是,在工作過程中碰到需要自訂刻度的情況,如所示
水平軸的刻度是5,10,20這樣的不均勻值,但是ExtJS不支援這樣的功能(至少我翻遍了文檔也沒找到)。最初想到的辦法是隱藏不需要的label,可這樣寫:
1 { 2 type: ‘Numeric‘, 3 position: ‘bottom‘, 4 fields: [‘x‘], 5 title: xAxisTitle, 6 minimum: xRange.xMinimum, 7 maximum: xRange.xMaximum, 8 majorTickSteps: 5, 9 minorTickSteps: 10,10 label: {11 renderer: function(val) {12 //lables: [5, 10, 20]13 if (labels.indexOf(val) < 0) {14 return ‘‘;15 }16 return val;17 }18 },19 grid: true20 }
但是這樣寫有兩個問題,一是需要顯示的label值不一定會出現在renderer中,二是即便label沒顯示,垂直的網格線(通過配置代碼中紅色部分的屬性可以調節網格線密度)還是會出現,這可能並不是我們想要的。通過查閱源碼發現,在座標軸內部實現中,是通過座標軸範圍和刻度個數來計算的,並且網格線跟座標刻度是一致的。在源碼檔案ext\src\chart\axis\Axis.js 480行:
1 // Build the array of steps out of the fixed-value ‘step‘.2 steps = new Array;3 for (val = +me.from; val < +me.to; val += step) {4 steps.push(val);5 }6 steps.push(+me.to);
之後渲染label和網格線都用到steps這個數組。所以,可以在這個地方做點手腳,把steps變數強行改成我們需要的數組,讓ExtJS按照我們的意圖去做。顯然,不能直接去修改Ext的源碼檔案。這裡有兩種辦法,一是用Ext.override方法去重寫Ext.chart.axis.Axis的drawAxis方法,二是在Axis的配置參數裡提供該方法的自訂實現。前者會影響到之後的所有用到座標軸的chart,後者只會影響當前的chart. 代碼改動如下:
1 Ext.syncRequire(‘Ext.chart.axis.Axis‘); 2 Ext.override(Ext.chart.axis.Axis, { 3 /** 4 * Renders the axis into the screen and updates its position. 5 */ 6 drawAxis: function(init) { 7 var me = this, 8 i, 9 x = me.x,10 y = me.y,11 dashSize = me.dashSize,12 length = me.length,13 position = me.position,14 verticalAxis = (position == ‘left‘ || position == ‘right‘),15 inflections = [],16 calcLabels = (me.isNumericAxis),17 stepCalcs = me.applyData(),18 step = stepCalcs.step,19 steps = stepCalcs.steps,20 stepsArray = Ext.isArray(steps),21 from = stepCalcs.from,22 to = stepCalcs.to,23 // If we have a single item, to - from will be 0.24 axisRange = (to - from) || 1,25 trueLength,26 currentX,27 currentY,28 path,29 subDashesX = me.minorTickSteps || 0,30 subDashesY = me.minorTickSteps || 0,31 dashesX = Math.max(subDashesX + 1, 0),32 dashesY = Math.max(subDashesY + 1, 0),33 dashDirection = (position == ‘left‘ || position == ‘top‘ ? -1 : 1),34 dashLength = dashSize * dashDirection,35 series = me.chart.series.items,36 firstSeries = series[0],37 gutters = firstSeries ? firstSeries.nullGutters : me.nullGutters,38 padding,39 subDashes,40 subDashValue,41 delta = 0,42 stepCount = 0,43 tick, axes, ln, val, begin, end;44 45 me.from = from;46 me.to = to;47 48 // If there is nothing to show, then leave. 49 if (me.hidden || (from > to)) {50 return;51 }52 53 // If no steps are specified (for instance if the store is empty), then leave.54 if ((stepsArray && (steps.length == 0)) || (!stepsArray && isNaN(step))) {55 return;56 }57 58 if (stepsArray) {59 // Clean the array of steps:60 // First remove the steps that are out of bounds.61 steps = Ext.Array.filter(steps, function(elem, index, array) {62 return (+elem > +me.from && +elem < +me.to);63 }, this);64 65 // Then add bounds on each side.66 steps = Ext.Array.union([me.from], steps, [me.to]);67 } else {68 // Build the array of steps out of the fixed-value ‘step‘.69 steps = new Array;70 if (me.fixedSteps) {71 steps = me.fixedSteps;72 } else {73 for (val = +me.from; val < +me.to; val += step) {74 steps.push(val);75 }76 steps.push(+me.to);77 }78 79 }80 ...//此處省略其他原有代碼81 }82 });
代碼中紅色部分if語句塊裡就是偷梁換柱的地方。使用的時候,在axis的配置代碼裡加上fixedSteps屬性就行了。
1 { 2 type: ‘Numeric‘, 3 position: ‘bottom‘, 4 fields: [‘x‘], 5 title: xAxisTitle, 6 minimum: xRange.xMinimum, 7 maximum: xRange.xMaximum, 8 fixedSteps: [5, 10,20], 9 grid: true10 }
至此,雕蟲小技大功告成。歡迎拍磚。