-
Notifications
You must be signed in to change notification settings - Fork 11.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Float-bar support. The logic is to use array values [bottomY, topY] i… #5262
Changes from 59 commits
a31d179
ceafcaf
f2e7310
d07f183
4ae0988
5b5bd25
88aa1a5
fc478a6
6075e6f
85ea4da
b4c2994
87e6e38
0e55557
0dd7666
8e44c5e
70a11e5
362d5f9
12525ce
4a366a2
69b8ab0
256729c
42add1c
0aad0c8
e414eb7
2161fc3
84e89aa
8bfa7e1
b12e2fe
786c5c4
861ed13
df32e68
10c3831
614275d
cf6fd4b
d5ef434
a75e3ac
aaaac73
5e877aa
823160e
11bb986
1c526e3
a59a602
a4efcf0
25ff4ea
7e75bef
03b8167
659235b
fe0772c
730e468
122167c
3e42297
9b95637
2af134b
a0e1231
a65aa3c
901c96f
7a42562
4f5332e
63ce9e9
b626b57
b25db90
8f06bc5
2a07aaa
d165e24
c4148e9
a48b8ce
e1095fa
14bccfe
f4d7413
5590350
9f88e05
76e9ceb
f957e64
2d06063
a786cd1
74dc634
dba5bdb
0e58967
124688c
84dae3d
19a400c
87b0d91
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -219,6 +219,11 @@ module.exports = function(Chart) { | |
var custom = rectangle.custom || {}; | ||
var rectangleOptions = chart.options.elements.rectangle; | ||
|
||
// float-bar support, if y arguments are array lets override rectangles styles, assigning no skippingBorder | ||
if (helpers.isArray(dataset.data[index])) { | ||
custom.borderSkipped = null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So does that means we will enforce There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, in fact we enforce this, cause float-bar will have all 4 sides required to be drawn, now sure if need to add smth else there. Or your idea to check the stacking here and make border skipped when 2 float-bars are stacked and one border should be eliminated. In my opinion in this case we will have 2 borders between 2 float-bars while stacking but thats better for vizualization purpose. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would consider changing this to cutom.borderSkipped = custom.borderSkipped !== undefined ? custom.borderSkipped : null; ie, if for whatever reason a bar has a custom skipped border setting, it will be kept otherwise there is no way for a user to draw partial borders on a floating bar |
||
} | ||
|
||
rectangle._xScale = me.getScaleForId(meta.xAxisID); | ||
rectangle._yScale = me.getScaleForId(meta.yAxisID); | ||
rectangle._datasetIndex = me.index; | ||
|
@@ -227,7 +232,7 @@ module.exports = function(Chart) { | |
rectangle._model = { | ||
datasetLabel: dataset.label, | ||
label: chart.data.labels[index], | ||
borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleOptions.borderSkipped, | ||
borderSkipped: helpers.valueOrDefault(custom.borderSkipped, rectangleOptions.borderSkipped), | ||
backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.valueAtIndexOrDefault(dataset.backgroundColor, index, rectangleOptions.backgroundColor), | ||
borderColor: custom.borderColor ? custom.borderColor : helpers.valueAtIndexOrDefault(dataset.borderColor, index, rectangleOptions.borderColor), | ||
borderWidth: custom.borderWidth ? custom.borderWidth : helpers.valueAtIndexOrDefault(dataset.borderWidth, index, rectangleOptions.borderWidth) | ||
|
@@ -383,11 +388,12 @@ module.exports = function(Chart) { | |
var meta = me.getMeta(); | ||
var scale = me.getValueScale(); | ||
var datasets = chart.data.datasets; | ||
var value = scale.getRightValue(datasets[datasetIndex].data[index]); | ||
var value = scale._parseValue(datasets[datasetIndex].data[index]); | ||
kurkle marked this conversation as resolved.
Show resolved
Hide resolved
|
||
var stacked = scale.options.stacked; | ||
var stack = meta.stack; | ||
var start = 0; | ||
var i, imeta, ivalue, base, head, size; | ||
var i, imeta, ivalue, base, head, size, yStackValue; | ||
kurkle marked this conversation as resolved.
Show resolved
Hide resolved
|
||
var start = value.max >= 0 && value.min >= 0 ? value.min : value.max; | ||
var yValue = value.max >= 0 && value.min >= 0 ? value.max - value.min : value.min - value.max; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would use the (
Another thing to consider is category axis for values. Say you have categories I think using
|
||
|
||
benmccann marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (stacked || (stacked === undefined && stack !== undefined)) { | ||
for (i = 0; i < datasetIndex; ++i) { | ||
|
@@ -397,17 +403,18 @@ module.exports = function(Chart) { | |
imeta.stack === stack && | ||
imeta.controller.getValueScaleId() === scale.id && | ||
chart.isDatasetVisible(i)) { | ||
yStackValue = scale._parseValue(datasets[i].data[index]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know how the stacking should work here. But, lets consider some scenarios: data = [[5, 6], 2, 3]
data = [1, [5, 7], 3]
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kurkle there was a discussion on the stacking behavior back in March. It was decided to go with option D as Simon described here: #5262 (comment) Hope that clarifies it! |
||
ivalue = yStackValue.min >= 0 && yStackValue.max >= 0 ? yStackValue.max : yStackValue.min; | ||
|
||
benmccann marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ivalue = scale.getRightValue(datasets[i].data[index]); | ||
if ((value < 0 && ivalue < 0) || (value >= 0 && ivalue > 0)) { | ||
if ((yValue < 0 && ivalue < 0) || (yValue >= 0 && ivalue >= 0)) { | ||
start += ivalue; | ||
} | ||
} | ||
} | ||
} | ||
|
||
base = scale.getPixelForValue(start); | ||
head = scale.getPixelForValue(start + value); | ||
head = scale.getPixelForValue(start + yValue); | ||
size = (head - base) / 2; | ||
|
||
return { | ||
|
@@ -453,8 +460,10 @@ module.exports = function(Chart) { | |
|
||
helpers.canvas.clipArea(chart.ctx, chart.chartArea); | ||
|
||
// float-bar support, if y arguments are array function will use bottom value as bar start point | ||
for (; i < ilen; ++i) { | ||
if (!isNaN(scale.getRightValue(dataset.data[i]))) { | ||
var val = scale._parseValue(dataset.data[i]); | ||
if (!isNaN(val.start) && !isNaN(val.end)) { | ||
rects[i].draw(); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -514,14 +514,16 @@ module.exports = Element.extend({ | |
|
||
// Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not | ||
getRightValue: function(rawValue) { | ||
// Null and undefined values first | ||
if (helpers.isNullOrUndef(rawValue)) { | ||
// Null and undefined values first. isNaN(object) returns true, so make sure NaN is checking for a number; Discard Infinite values | ||
if (helpers.isNullOrUndef(rawValue) || (typeof rawValue === 'number' && !isFinite(rawValue))) { | ||
return NaN; | ||
} | ||
// isNaN(object) returns true, so make sure NaN is checking for a number; Discard Infinite values | ||
if (typeof rawValue === 'number' && !isFinite(rawValue)) { | ||
return NaN; | ||
|
||
// Float-bar support. Handling arrays | ||
if (helpers.isArray(rawValue)) { | ||
return [this.getRightValue(rawValue[0]), this.getRightValue(rawValue[1])]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This also allows data like |
||
} | ||
|
||
// If it is in fact an object, dive in one more level | ||
if (rawValue) { | ||
if (this.isHorizontal()) { | ||
|
@@ -537,6 +539,30 @@ module.exports = Element.extend({ | |
return rawValue; | ||
}, | ||
|
||
/** | ||
* @private | ||
* Parse array and generic values into object | ||
*/ | ||
_parseValue: function(raw) { | ||
var value = this.getRightValue(raw); | ||
var start, end; | ||
|
||
if (helpers.isArray(value)) { | ||
start = value[0]; | ||
end = value[1]; | ||
} else { | ||
start = 0; | ||
end = value; | ||
} | ||
|
||
return { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would consider calculating |
||
min: Math.min(start, end), | ||
max: Math.max(start, end), | ||
start: start, | ||
end: end | ||
}; | ||
}, | ||
|
||
/** | ||
* Used to get the value to display in the tooltip for the data at the given index | ||
* @param index | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -74,20 +74,27 @@ module.exports = function(Chart) { | |
|
||
if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { | ||
helpers.each(dataset.data, function(rawValue, index) { | ||
var value = +me.getRightValue(rawValue); | ||
if (isNaN(value) || meta.data[index].hidden) { | ||
var value = me._parseValue(rawValue); | ||
|
||
if (isNaN(value.min) || isNaN(value.max) || meta.data[index].hidden) { | ||
return; | ||
} | ||
|
||
positiveValues[index] = positiveValues[index] || 0; | ||
negativeValues[index] = negativeValues[index] || 0; | ||
|
||
if (value.min === 0) { | ||
value.min = value.max; | ||
} else if (value.max === 0) { | ||
value.max = value.min; | ||
} | ||
|
||
if (opts.relativePoints) { | ||
positiveValues[index] = 100; | ||
} else if (value < 0) { | ||
negativeValues[index] += value; | ||
} else if (value.min < 0) { | ||
negativeValues[index] += value.min; | ||
} else { | ||
positiveValues[index] += value; | ||
positiveValues[index] += value.max; | ||
} | ||
}); | ||
} | ||
|
@@ -106,21 +113,28 @@ module.exports = function(Chart) { | |
var meta = chart.getDatasetMeta(datasetIndex); | ||
if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { | ||
helpers.each(dataset.data, function(rawValue, index) { | ||
var value = +me.getRightValue(rawValue); | ||
if (isNaN(value) || meta.data[index].hidden) { | ||
var value = me._parseValue(rawValue); | ||
|
||
if (isNaN(value.min) || isNaN(value.max) || meta.data[index].hidden) { | ||
return; | ||
} | ||
|
||
if (value.min === 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this block will cause a problem if the user draws a floating bar with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hi @etimberg! We had to force to this check in order to keep the logic of scale building, its ok that 0 will not pass to scale values. Without this check some unit tests were not passed cause generally scale should not take account of 0 as start point. [0, 10] is not actually a float-bar, it has standartized representation as array but in fact its another view of 10. So, if we pass 10 this will be treated as [0,10]. So, scale should only take 10 and not zero. The reason why we should omit this 0 - for example we will use for bulding bars two values - 1 and 2. The new logic will treat them as [0,1] and [0,2]. WE have three uniq values here - 0, 1, 2. If scale will take all of them it will build scale from 0 to 2. According to general logic (without treating as arrays) it will build scale only from 1 to 2. We will have pixels difference in case of standart as integers or new logic (as arrays) values for graphs. SO this check is checking if the zero is actually a new value that should be passed to scale or its just for compability of old and new methods. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gwyneblaidd sounds good. I wanted to make sure this was expected since the case I highlighted might cause some confusion. If you haven't already, would it be possible to include this in the documentation of the float bar feature? That way other users would know to simply pass the value they expect |
||
value.min = value.max; | ||
} else if (value.max === 0) { | ||
value.max = value.min; | ||
} | ||
|
||
if (me.min === null) { | ||
me.min = value; | ||
} else if (value < me.min) { | ||
me.min = value; | ||
me.min = value.min; | ||
} else if (value.min < me.min) { | ||
me.min = value.min; | ||
} | ||
|
||
if (me.max === null) { | ||
me.max = value; | ||
} else if (value > me.max) { | ||
me.max = value; | ||
me.max = value.max; | ||
} else if (value.max > me.max) { | ||
me.max = value.max; | ||
} | ||
}); | ||
} | ||
|
@@ -156,7 +170,8 @@ module.exports = function(Chart) { | |
} | ||
}, | ||
getLabelForIndex: function(index, datasetIndex) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this method is the same in both the linear and logarithmic scales. perhaps we should move it to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); | ||
var v = this._parseValue(this.chart.data.datasets[datasetIndex].data[index]); | ||
return v.start === 0 ? v.end : v.start + ' ; ' + v.end; | ||
gwyneblaidd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}, | ||
// Utils | ||
getPixelForValue: function(value) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would change this to something like
For floating bar char you can use array of [start, end] for a point, where both start and end are values accepted by the scale used