PDA

View Full Version : [CLOSED] [4.2.1 beta] Chart ScatterSeries and LineSeries can render incorrect labels



Daniil
1 May 2013, 10:33 PM
REQUIRED INFORMATION

Ext version tested:

Ext 4.2.1 beta

Browser versions tested against:

IE9
Chrome

DOCTYPE tested against:

<!DOCTYPE html>

Description:

A ScatterSeries and LineSeries render incorrect labels if some of the points are missed (i.e. its yField is undefined).

Steps to reproduce the problem:

Just run the test case

The result that was expected:

"Item 0", "Item 2", "Item 4" labels

The result that occurs instead:

"Item 0", "Item 1", "Item 2" labels

Test Case:


<!DOCTYPE html>
<html>
<head>
<title>ScatterSeries and LineSeries renders incorrect labels</title>

<link rel="stylesheet" href="../resources/css/ext-all.css" />

<script src="../ext-all-debug.js"></script>

<script>
Ext.onReady(function () {
var store = Ext.create("Ext.data.Store", {
autoLoad: true,
fields: [{
name: "x"
}, {
name: "y"
}, {
name: "label"
}],
data: [{
x: 0,
y: 0,
label: "Item 0"
}, {
x: 1,
y: undefined,
label: "Item 1"
}, {
x: 2,
y: 2,
label: "Item 2"
}, {
x: 3,
y: undefined,
label: "Item 3"
}, {
x: 4,
y: 4,
label: "Item 4"
}]
});

Ext.create("Ext.chart.Chart", {
renderTo: Ext.getBody(),
width: 300,
height: 300,
store: store,
axes: [{
type: "Numeric",
position: "bottom",
title: "X",
fields: ["x"],
maximum: 5
}, {
type: "Numeric",
position: "left",
title: "Y",
fields: ["y"],
maximum: 5
}],
series: [{
type: "scatter",
xField: "x",
yField: "y",
label: {
field: "label",
display: "over"
}
}]
});
});
</script>
</head>
<body>

</body>
</html>



HELPFUL INFORMATION

Possible fix:

I think the problem is in the Ext.chart.Label's renderLabels method. See the red text. Tested with a Line and a Scatter series. I have not tested with another types of series.


Ext.chart.series.Series.override({
renderLabels: function () {
var me = this,
chart = me.chart,
gradients = chart.gradients,
items = me.items,
animate = chart.animate,
config = me.label,
display = config.display,
stackedDisplay = config.stackedDisplay,
format = config.renderer,
color = config.color,
field = [].concat(config.field),
group = me.labelsGroup,
groupLength = (group || 0) && group.length,
store = me.chart.getChartStore(),
len = store.getCount(),
itemLength = (items || 0) && items.length,
ratio = itemLength / len,
gradientsCount = (gradients || 0) && gradients.length,
Color = Ext.draw.Color,
hides = [],
gradient, i, count, groupIndex, index, j, k, colorStopTotal, colorStopIndex, colorStop, item, label,
storeItem, sprite, spriteColor, spriteBrightness, labelColor, colorString,
total, totalPositive, totalNegative, topText, bottomText;

if (display == 'none') {
return;
}
// no items displayed, hide all labels
if (itemLength == 0) {
while (groupLength--) {
hides.push(groupLength);
}
} else {
for (i = 0, count = 0, groupIndex = 0; i < len; i++) {
index = 0;
for (j = 0; j < ratio; j++) {
item = items[count];
label = group.getAt(groupIndex);
storeItem = item && item.storeItem; //storeItem = store.getAt(i); - replaced
//check the excludes
while (this.__excludes && this.__excludes[index]) {
index++;
}

if (!item && label) {
label.hide(true);
groupIndex++;
}

if (item && field[j]) {
if (!label) {
label = me.onCreateLabel(storeItem, item, i, display);
}
me.onPlaceLabel(label, storeItem, item, i, display, animate, index);
groupIndex++;

//set contrast
if (config.contrast && item.sprite) {
sprite = item.sprite;
//set the color string to the color to be set, only read the
// _endStyle/_to if we're animating, otherwise they're not relevant
if (animate && sprite._endStyle) {
colorString = sprite._endStyle.fill;
} else if (animate && sprite._to) {
colorString = sprite._to.fill;
} else {
colorString = sprite.attr.fill;
}
colorString = colorString || sprite.attr.fill;

spriteColor = Color.fromString(colorString);
//color wasn't parsed property maybe because it's a gradient id
if (colorString && !spriteColor) {
colorString = colorString.match(me.colorStringRe)[1];
for (k = 0; k < gradientsCount; k++) {
gradient = gradients[k];
if (gradient.id == colorString) {
//avg color stops
colorStop = 0;
colorStopTotal = 0;
for (colorStopIndex in gradient.stops) {
colorStop++;
colorStopTotal += Color.fromString(gradient.stops[colorStopIndex].color).getGrayscale();
}
spriteBrightness = (colorStopTotal / colorStop) / 255;
break;
}
}
} else {
spriteBrightness = spriteColor.getGrayscale() / 255;
}
if (label.isOutside) {
spriteBrightness = 1;
}
labelColor = Color.fromString(label.attr.color || label.attr.fill).getHSL();
labelColor[2] = spriteBrightness > 0.5 ? 0.2 : 0.8;
label.setAttributes({
fill: String(Color.fromHSL.apply({}, labelColor))
}, true);
}

// display totals on stacked charts
if (me.stacked && stackedDisplay && (item.totalPositiveValues || item.totalNegativeValues)) {
totalPositive = (item.totalPositiveValues || 0);
totalNegative = (item.totalNegativeValues || 0);
total = totalPositive + totalNegative;

if (stackedDisplay == 'total') {
topText = format(total);
} else if (stackedDisplay == 'balances') {
if (totalPositive == 0 && totalNegative == 0) {
topText = format(0);
} else {
topText = format(totalPositive);
bottomText = format(totalNegative);
}
}

if (topText) {
label = group.getAt(groupIndex);
if (!label) {
label = me.onCreateLabel(storeItem, item, i, 'over');
}
label.setAttributes({
text: topText
});
me.onPlaceLabel(label, storeItem, item, i, 'over', animate, index);
groupIndex++;

labelColor = Color.fromString(label.attr.color || label.attr.fill).getHSL();
label.setAttributes({
fill: String(Color.fromHSL.apply({}, labelColor))
}, true);
}

if (bottomText) {
label = group.getAt(groupIndex);
if (!label) {
label = me.onCreateLabel(storeItem, item, i, 'under');
}
label.setAttributes({
text: bottomText
});
me.onPlaceLabel(label, storeItem, item, i, 'under', animate, index);
groupIndex++;

labelColor = Color.fromString(label.attr.color || label.attr.fill).getHSL();
label.setAttributes({
fill: String(Color.fromHSL.apply({}, labelColor))
}, true);
}
}
}
count++;
index++;
}
}
groupLength = group.length;

while (groupLength > groupIndex) {
hides.push(groupIndex);
groupIndex++;
}
}
me.hideLabels(hides);
}
});


*EDIT BY SLEMMON
tested in 4.1.1
tested in 4.1.3
tested in 4.2.1.799

slemmon
2 May 2013, 8:41 AM
Thanks for the report! I have opened a bug in our bug tracker.

Daniil
2 May 2013, 8:38 PM
I think the problem is in the Ext.chart.Label's renderLabels method. I have updated the initial post with a Possible Fix section.