不知道该如何改,求高人指点
经实践验证可行:
Ext.override(Ext.chart.axis.Time, {
drawAxis: function (init) {
var me = this,
filterFnScope = me.filterFnScope || this, // AJW: scope for the filterInflection() function
filterInflection = me.filterInflection || function() { return true; }, // AJW: filter inflection function
zoomX = me.zoomX,
zoomY = me.zoomY,
x = me.startX * zoomX,
y = me.startY * zoomY,
gutterX = me.chart.maxGutter[0] * zoomX,
gutterY = me.chart.maxGutter[1] * zoomY,
dashSize = me.dashSize,
subDashesX = me.minorTickSteps || 0,
subDashesY = me.minorTickSteps || 0,
isSide = me.isSide(),
viewLength = me.length,
bufferLength = viewLength * me.overflowBuffer,
totalLength = viewLength * (isSide ? zoomY : zoomX),
position = me.position,
inflections = [],
calcLabels = me.calcLabels,
stepCalcs = me.applyData(),
step = stepCalcs.step,
from = stepCalcs.from,
to = stepCalcs.to,
math = Math,
mfloor = math.floor,
mmax = math.max,
mmin = math.min,
mround = math.round,
trueLength, currentX, currentY, startX, startY, path, dashesX, dashesY, delta, skipTicks, i,
index; // AJW: added index var
me.updateSurfaceBox();
//If no steps are specified
//then don't draw the axis. This generally happens
//when an empty store.
if (me.hidden || me.chart.store.getCount() < 1 || stepCalcs.steps <= 0) {
me.getSurface().items.hide(true);
if (me.displaySprite) {
me.displaySprite.hide(true);
}
return;
}
me.from = stepCalcs.from;
me.to = stepCalcs.to;
if (isSide) {
currentX = mfloor(x) + 0.5;
path = ["M", currentX, y, "l", 0, -totalLength];
trueLength = totalLength - (gutterY * 2);
}
else {
currentY = mfloor(y) + 0.5;
path = ["M", x, currentY, "l", totalLength, 0];
trueLength = totalLength - (gutterX * 2);
}
delta = trueLength * step / (to - from);
skipTicks = me.skipTicks = mfloor(mmax(0, (isSide ? totalLength + me.panY - viewLength - bufferLength : -me.panX - bufferLength)) / delta);
dashesX = mmax(subDashesX +1, 0);
dashesY = mmax(subDashesY +1, 0);
if (calcLabels) {
me.labels = [stepCalcs.from + skipTicks * step];
}
if (isSide) {
currentY = startY = y - gutterY - delta * skipTicks;
currentX = x - ((position == 'left') * dashSize * 2);
while (currentY >= startY - mmin(trueLength, viewLength + bufferLength * 2)) {
path.push("M", currentX, mfloor(currentY) + 0.5, "l", dashSize * 2 + 1, 0);
if (currentY != startY) {
for (i = 1; i < dashesY; i++) {
path.push("M", currentX + dashSize, mfloor(currentY + delta * i / dashesY) + 0.5, "l", dashSize + 1, 0);
}
}
inflections.push([ mfloor(x), mfloor(currentY) ]);
currentY -= delta;
if (calcLabels) {
// Cut everything that is after tenth digit after floating point. This is to get rid of
// rounding errors, i.e. 12.00000000000121212.
me.labels.push(+(me.labels[me.labels.length - 1] + step).toFixed(10));
}
if (delta === 0) {
break;
}
}
if (mround(currentY + delta - (y - gutterY - trueLength))) {
path.push("M", currentX, mfloor(y - totalLength + gutterY) + 0.5, "l", dashSize * 2 + 1, 0);
for (i = 1; i < dashesY; i++) {
path.push("M", currentX + dashSize, mfloor(y - totalLength + gutterY + delta * i / dashesY) + 0.5, "l", dashSize + 1, 0);
}
inflections.push([ mfloor(x), mfloor(currentY) ]);
if (calcLabels) {
// Cut everything that is after tenth digit after floating point. This is to get rid of
// rounding errors, i.e. 12.00000000000121212.
me.labels.push(+(me.labels[me.labels.length - 1] + step).toFixed(10));
}
}
} else {
// AJW: initialize the index for the filterInflection function
index = -1;
currentX = startX = x + gutterX + delta * skipTicks;
currentY = y - ((position == 'top') * dashSize * 2);
while (currentX <= startX + mmin(trueLength, viewLength + bufferLength * 2)) {
// AJW: increment the index for the filterInflection function
index++;
// AJW: if the filterInflection function returns false, then we don't want an inflection, label
// and dash(es) for this data point. In this case we just push null onto the inflections array
// to a) maintain a one-to-one correspondence between data points, inflections and labels and
// b) indicate to the code that we don't want to render a grid line and label for this inflection.
if (!filterInflection.call(filterFnScope, index)) {
inflections.push(null);
} else {
path.push("M", mfloor(currentX) + 0.5, currentY, "l", 0, dashSize * 2 + 1);
if (currentX != startX) {
for (i = 1; i < dashesX; i++) {
path.push("M", mfloor(currentX - delta * i / dashesX) + 0.5, currentY, "l", 0, dashSize + 1);
}
}
inflections.push([ mfloor(currentX), mfloor(y) ]);
}
currentX += delta;
if (calcLabels) {
// Cut everything that is after tenth digit after floating point. This is to get rid of
// rounding errors, i.e. 12.00000000000121212.
me.labels.push(+(me.labels[me.labels.length - 1] + step).toFixed(10));
}
if (delta === 0) {
break;
}
}
if (mround(currentX - delta - (x + gutterX + trueLength))) {
path.push("M", mfloor(x + totalLength - gutterX) + 0.5, currentY, "l", 0, dashSize * 2 + 1);
for (i = 1; i < dashesX; i++) {
path.push("M", mfloor(x + totalLength - gutterX - delta * i / dashesX) + 0.5, currentY, "l", 0, dashSize + 1);
}
inflections.push([mfloor(currentX), mfloor(y) ]);
if (calcLabels) {
// Cut everything that is after tenth digit after floating point. This is to get rid of
// rounding errors, i.e. 12.00000000000121212.
me.labels.push(+(me.labels[me.labels.length - 1] + step).toFixed(10));
}
}
}
if (!me.axis) {
me.axis = me.getSurface().add(Ext.apply({
type: 'path',
path: path
}, me.style));
}
me.axis.setAttributes({
path: path,
hidden: false
}, true);
me.inflections = inflections;
if (!init) {
//if grids have been styled in some way
if ( me.grid ||
me.gridStyle.style ||
me.gridStyle.oddStyle.style ||
me.gridStyle.evenStyle.style ) {
me.drawGrid();
}
}
me.axisBBox = me.axis.getBBox();
me.drawLabel();
},
/**
* Renders an horizontal and/or vertical grid into the Surface.
*/
drawGrid: function() {
var me = this,
surface = me.getSurface(),
grid = me.gridStyle.style || me.grid,
odd = me.gridStyle.oddStyle.style || grid.odd,
even = me.gridStyle.evenStyle.style || grid.even,
inflections = me.inflections,
ln = inflections.length - ((odd || even)? 0 : 1),
position = me.position,
gutter = me.chart.maxGutter,
width = me.width - 2,
point, prevPoint,
i = 1,
isSide = me.isSide(),
path = [], styles, lineWidth, dlineWidth,
oddPath = [], evenPath = [];
if ((gutter[1] !== 0 && isSide) ||
(gutter[0] !== 0 && !isSide)) {
i = 0;
ln++;
}
for (; i < ln; i++) {
point = inflections[i];
// AJW: if point is null, this means that a grid line is not wanted for this inflection.
if (point === null) {
continue;
}
prevPoint = inflections[i - 1];
if (odd || even) {
path = (i % 2)? oddPath : evenPath;
styles = ((i % 2)? odd : even) || {};
lineWidth = (styles.lineWidth || styles['stroke-width'] || 0) / 2;
dlineWidth = 2 * lineWidth;
if (position == 'left') {
path.push("M", prevPoint[0] + 1 + lineWidth, prevPoint[1] + 0.5 - lineWidth,
"L", prevPoint[0] + 1 + width - lineWidth, prevPoint[1] + 0.5 - lineWidth,
"L", point[0] + 1 + width - lineWidth, point[1] + 0.5 + lineWidth,
"L", point[0] + 1 + lineWidth, point[1] + 0.5 + lineWidth, "Z");
}
else if (position == 'right') {
path.push("M", prevPoint[0] - lineWidth, prevPoint[1] + 0.5 - lineWidth,
"L", prevPoint[0] - width + lineWidth, prevPoint[1] + 0.5 - lineWidth,
"L", point[0] - width + lineWidth, point[1] + 0.5 + lineWidth,
"L", point[0] - lineWidth, point[1] + 0.5 + lineWidth, "Z");
}
else if (position == 'top') {
path.push("M", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] + 1 + lineWidth,
"L", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] + 1 + width - lineWidth,
"L", point[0] + 0.5 - lineWidth, point[1] + 1 + width - lineWidth,
"L", point[0] + 0.5 - lineWidth, point[1] + 1 + lineWidth, "Z");
}
else {
path.push("M", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] - lineWidth,
"L", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] - width + lineWidth,
"L", point[0] + 0.5 - lineWidth, point[1] - width + lineWidth,
"L", point[0] + 0.5 - lineWidth, point[1] - lineWidth, "Z");
}
} else {
if (position == 'left') {
path = path.concat(["M", point[0] + 0.5, point[1] + 0.5, "l", width, 0]);
}
else if (position == 'right') {
path = path.concat(["M", point[0] - 0.5, point[1] + 0.5, "l", -width, 0]);
}
else if (position == 'top') {
path = path.concat(["M", point[0] + 0.5, point[1] + 0.5, "l", 0, width]);
}
else {
path = path.concat(["M", point[0] + 0.5, point[1] - 0.5, "l", 0, -width]);
}
}
}
if (odd || even) {
if (oddPath.length) {
if (!me.gridOdd && oddPath.length) {
me.gridOdd = surface.add({
type: 'path',
path: oddPath
});
}
me.gridOdd.setAttributes(Ext.apply({
path: oddPath,
hidden: false
}, odd || {}), true);
}
if (evenPath.length) {
if (!me.gridEven) {
me.gridEven = surface.add({
type: 'path',
path: evenPath
});
}
me.gridEven.setAttributes(Ext.apply({
path: evenPath,
hidden: false
}, even || {}), true);
}
}
else {
if (path.length) {
if (!me.gridLines) {
me.gridLines = me.getSurface().add({
type: 'path',
path: path,
"stroke-width": me.lineWidth || 1,
stroke: me.gridColor || '#ccc'
});
}
me.gridLines.setAttributes({
hidden: false,
path: path
}, true);
}
else if (me.gridLines) {
me.gridLines.hide(true);
}
}
},
drawHorizontalLabels: function() {
var me = this,
labelConf = me.labelStyle.style,
renderer = labelConf.renderer || function(v) {
return v;
},
math = Math,
floor = math.floor,
max = math.max,
axes = me.chart.axes,
position = me.position,
inflections = me.inflections,
ln = inflections.length,
labels = me.labels,
skipTicks = me.skipTicks,
maxHeight = 0,
ratio,
bbox, point, prevLabel,
textLabel, text,
last, x, y, i, firstLabel;
if (!me.calcLabels && skipTicks) {
labels = labels.slice(skipTicks);
ln -= skipTicks;
}
last = ln - 1;
//get a reference to the first text label dimensions
point = inflections[0];
firstLabel = me.getOrCreateLabel(0, renderer(labels[0]));
ratio = math.abs(math.sin(labelConf.rotate && (labelConf.rotate.degrees * math.PI / 180) || 0)) >> 0;
for (i = 0; i < ln; i++) {
point = inflections[i];
// AJW: if point is null, this means that a label is not wanted for this inflection.
if (point === null) {
// AJW: not optimal, and I don't particularly like it, but I had to explicitly put in this
// call to hide labels because otherwise changing the store data (e.g. changing time period
// selection) won't clear the previously-rendered labels, and labels would overwrite each
// other and look very messy.
me.getOrCreateLabel(i, text).hide(true);
continue;
}
text = renderer(labels[i]);
textLabel = me.getOrCreateLabel(i, text);
bbox = textLabel._bbox;
maxHeight = max(maxHeight, bbox.height + me.dashSize + (labelConf.padding || 0));
x = floor(point[0] - (ratio? bbox.height : bbox.width) / 2);
if (me.chart.maxGutter[0] == 0) {
if (i == 0 && axes.findIndex('position', 'left') == -1) {
x = point[0];
}
else if (i == last && axes.findIndex('position', 'right') == -1) {
x = point[0] - bbox.width;
}
}
if (position == 'top') {
y = point[1] - (me.dashSize * 2) - labelConf.padding - (bbox.height / 2);
}
else {
y = point[1] + (me.dashSize * 2) + labelConf.padding + (bbox.height / 2);
}
if (!me.isPannable()) {
x += me.x;
y += me.y;
}
textLabel.setAttributes({
hidden: false,
x: x,
y: y
}, true);
if (labelConf.rotate) {
textLabel.setAttributes(labelConf, true);
}
// Skip label if there isn't available minimum space
if (i != 0 && (me.intersect(textLabel, prevLabel)
|| me.intersect(textLabel, firstLabel))) {
textLabel.hide(true);
continue;
}
prevLabel = textLabel;
}
return maxHeight;
},
});
time轴引用
{
type: 'Time',
position: 'bottom',
fields: ['DateTime'],
dateFormat: 'Y M d h:i:s',
grid: true,
groupBy: 'year,month,day,hour',
aggregateOp: 'avg',
filterFnScope: this,
filterInflection: function(index) {
return ((index%30) === 0);
},
label: {
renderer:function(item) {
return item;
},
rotate: {
degrees: 0
}
},
title: 'DateTime'
}
结果可行:如图