style: {},
<span id='Ext-chart-series-Line-cfg-smooth'> /**
-</span> * @cfg {Boolean} smooth
- * If true, the line will be smoothed/rounded around its points, otherwise straight line
- * segments will be drawn. Defaults to false.
+</span> * @cfg {Boolean/Number} smooth
+ * If set to `true` or a non-zero number, the line will be smoothed/rounded around its points; otherwise
+ * straight line segments will be drawn.
+ *
+ * A numeric value is interpreted as a divisor of the horizontal distance between consecutive points in
+ * the line; larger numbers result in sharper curves while smaller numbers result in smoother curves.
+ *
+ * If set to `true` then a default numeric value of 3 will be used. Defaults to `false`.
*/
smooth: false,
+<span id='Ext-chart-series-Line-property-defaultSmoothness'> /**
+</span> * @private Default numeric smoothing value to be used when {@link #smooth} = true.
+ */
+ defaultSmoothness: 3,
+
<span id='Ext-chart-series-Line-cfg-fill'> /**
</span> * @cfg {Boolean} fill
* If true, the area below the line will be filled in using the {@link #style.eefill} and
markerGroup = me.markerGroup,
enableShadows = chart.shadow,
shadowGroups = me.shadowGroups,
- shadowAttributes = this.shadowAttributes,
+ shadowAttributes = me.shadowAttributes,
+ smooth = me.smooth,
lnsh = shadowGroups.length,
dummyPath = ["M"],
path = ["M"],
shadowBarAttr,
xValues = [],
yValues = [],
+ storeIndices = [],
numericAxis = true,
axisCount = 0,
onbreak = false,
'top': 'bottom',
'bottom': 'top'
},
+ isNumber = Ext.isNumber,
seriesIdx = me.seriesIdx, shadows, shadow, shindex, fromPath, fill, fillPath, rendererAttributes,
x, y, prevX, prevY, firstY, markerCount, i, j, ln, axis, ends, marker, markerAux, item, xValue,
yValue, coords, xScale, yScale, minX, maxX, minY, maxY, line, animation, endMarkerStyle,
- endLineStyle, type, props, firstMarker, count;
+ endLineStyle, type, props, firstMarker, count, smoothPath, renderPath;
//if store is empty then there's nothing to draw.
if (!store || !store.getCount()) {
// If a field was specified without a corresponding axis, create one to get bounds
//only do this for the axis where real values are bound (that's why we check for
//me.axis)
- if (me.xField && !Ext.isNumber(minX)) {
+ if (me.xField && !isNumber(minX)) {
if (me.axis == 'bottom' || me.axis == 'top') {
axis = Ext.create('Ext.chart.axis.Axis', {
chart: chart,
}
}
- if (me.yField && !Ext.isNumber(minY)) {
+ if (me.yField && !isNumber(minY)) {
if (me.axis == 'right' || me.axis == 'left') {
axis = Ext.create('Ext.chart.axis.Axis', {
chart: chart,
xScale = bbox.width / (store.getCount() - 1);
}
else {
- xScale = bbox.width / (maxX - minX);
+ //In case some person decides to set an axis' minimum and maximum
+ //configuration properties to the same value, then fallback the
+ //denominator to a > 0 value.
+ xScale = bbox.width / ((maxX - minX) || (store.getCount() - 1));
}
if (isNaN(minY)) {
yScale = bbox.height / (store.getCount() - 1);
}
else {
- yScale = bbox.height / (maxY - minY);
+ //In case some person decides to set an axis' minimum and maximum
+ //configuration properties to the same value, then fallback the
+ //denominator to a > 0 value.
+ yScale = bbox.height / ((maxY - minY) || (store.getCount() - 1));
}
store.each(function(record, i) {
|| (me.axis != 'left' && me.axis != 'right' && !numericAxis)) {
yValue = i;
}
+ storeIndices.push(i);
xValues.push(xValue);
yValues.push(yValue);
}, me);
};
}
}
+
me.items.push({
series: me,
value: [xValue, yValue],
point: [x, y],
sprite: marker,
- storeItem: store.getAt(i)
+ storeItem: store.getAt(storeIndices[i])
});
prevX = x;
prevY = y;
//nothing to be rendered
return;
}
-
- if (me.smooth) {
- path = Ext.draw.Draw.smooth(path, 6);
+
+ if (smooth) {
+ smoothPath = Ext.draw.Draw.smooth(path, isNumber(smooth) ? smooth : me.defaultSmoothness);
}
+ renderPath = smooth ? smoothPath : path;
+
//Correct path if we're animating timeAxis intervals
if (chart.markerIndex && me.previousPath) {
fromPath = me.previousPath;
- fromPath.splice(1, 2);
+ if (!smooth) {
+ Ext.Array.erase(fromPath, 1, 2);
+ }
} else {
fromPath = path;
}
-
+
// Only create a line if one doesn't exist.
if (!me.line) {
me.line = surface.add(Ext.apply({
}
}
if (me.fill) {
- fillPath = path.concat([
+ fillPath = renderPath.concat([
["L", x, bbox.y + bbox.height],
["L", bbox.x, bbox.y + bbox.height],
["L", bbox.x, firstY]
group: group,
type: 'path',
opacity: endLineStyle.opacity || 0.3,
- fill: colorArrayStyle[seriesIdx % colorArrayLength] || endLineStyle.fill,
+ fill: endLineStyle.fill || colorArrayStyle[seriesIdx % colorArrayLength],
path: dummyPath
});
}
fill = me.fill;
line = me.line;
//Add renderer to line. There is not unique record associated with this.
- rendererAttributes = me.renderer(line, false, { path: path }, i, store);
+ rendererAttributes = me.renderer(line, false, { path: renderPath }, i, store);
Ext.apply(rendererAttributes, endLineStyle || {}, {
stroke: endLineStyle.stroke || endLineStyle.fill
});
for(j = 0; j < lnsh; j++) {
if (chart.markerIndex && me.previousPath) {
me.onAnimate(shadows[j], {
- to: { path: path },
+ to: { path: renderPath },
from: { path: fromPath }
});
} else {
me.onAnimate(shadows[j], {
- to: { path: path }
+ to: { path: renderPath }
});
}
}
me.onAnimate(me.fillPath, {
to: Ext.apply({}, {
path: fillPath,
- fill: colorArrayStyle[seriesIdx % colorArrayLength] || endLineStyle.fill
+ fill: endLineStyle.fill || colorArrayStyle[seriesIdx % colorArrayLength]
}, endLineStyle || {})
});
}
}
}
} else {
- rendererAttributes = me.renderer(me.line, false, { path: path, hidden: false }, i, store);
+ rendererAttributes = me.renderer(me.line, false, { path: renderPath, hidden: false }, i, store);
Ext.apply(rendererAttributes, endLineStyle || {}, {
stroke: endLineStyle.stroke || endLineStyle.fill
});
shadows = me.line.shadows;
for(j = 0; j < lnsh; j++) {
shadows[j].setAttributes({
- path: path
+ path: renderPath
}, true);
}
}
}
if (chart.markerIndex) {
- path.splice(1, 0, path[1], path[2]);
+ if (me.smooth) {
+ Ext.Array.erase(path, 1, 2);
+ } else {
+ Ext.Array.splice(path, 1, 0, path[1], path[2]);
+ }
me.previousPath = path;
}
me.renderLabels();