-
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
Improve offset calculation for scale.offset option #4658
Changes from 2 commits
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 |
---|---|---|
|
@@ -361,27 +361,55 @@ function generate(min, max, capacity, options) { | |
* Returns the right and left offsets from edges in the form of {left, right}. | ||
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. Can you clarify more what this offset it. What is it that gets offset and why does it need to be offset? 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. Does this make sense?
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. Super helpful! To clarify: 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. Ok, it's "the edges of the chart". |
||
* Offsets are added when the `offset` option is true. | ||
*/ | ||
function computeOffsets(table, ticks, min, max, options) { | ||
function computeOffsets(table, ticks, data, min, max, options) { | ||
var pos = []; | ||
var minInterval = 1; | ||
var timeOpts = options.time; | ||
var barThickness = options.barThickness; | ||
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. Accessing |
||
var left = 0; | ||
var right = 0; | ||
var upper, lower; | ||
|
||
if (options.offset && ticks.length) { | ||
if (!options.time.min) { | ||
upper = ticks.length > 1 ? ticks[1] : max; | ||
lower = ticks[0]; | ||
left = ( | ||
interpolate(table, 'time', upper, 'pos') - | ||
interpolate(table, 'time', lower, 'pos') | ||
) / 2; | ||
} | ||
if (!options.time.max) { | ||
upper = ticks[ticks.length - 1]; | ||
lower = ticks.length > 1 ? ticks[ticks.length - 2] : min; | ||
right = ( | ||
interpolate(table, 'time', upper, 'pos') - | ||
interpolate(table, 'time', lower, 'pos') | ||
) / 2; | ||
var i, ilen, curr, prev, length, width; | ||
|
||
if (options.offset) { | ||
data.forEach(function(timestamp) { | ||
if (timestamp >= min && timestamp <= max) { | ||
pos.push(interpolate(table, 'time', timestamp, 'pos')); | ||
} | ||
}); | ||
|
||
length = pos.length; | ||
if (length) { | ||
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. Can this be combined with the enclosing 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. Even if 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. Ah, you're right. Maybe we could also invert the check. E.g.:
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. As this function needs to return an object, I will just move the check. 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. It could make the code slightly easier to read and remove a lot of indentation if we reversed this if statement:
You could do the same just above with the 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. Agreed. Will update it. |
||
// Calculate minInterval | ||
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 is a bit nit picky, but I would actually move this comment down a line (i.e. right above 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. Ok, agreed. |
||
if (!barThickness) { | ||
[data, ticks].forEach(function(timestamps) { | ||
for (i = 0, ilen = timestamps.length; i < ilen; ++i) { | ||
curr = interpolate(table, 'time', timestamps[i], 'pos'); | ||
minInterval = i > 0 ? Math.min(minInterval, curr - prev) : minInterval; | ||
prev = curr; | ||
} | ||
}); | ||
} | ||
|
||
if (!timeOpts.min) { | ||
if (length === 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. What if 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 is the case that there is only one data point within the range. 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. Thanks. I missed that it was filtered out up above |
||
width = (1 - pos[0]) * 2; | ||
} else if (barThickness) { | ||
width = pos[1] - pos[0]; | ||
} else { | ||
width = minInterval; | ||
} | ||
left = Math.max(width / 2 - pos[0], 0); | ||
} | ||
if (!timeOpts.max) { | ||
if (length === 1) { | ||
width = pos[0] * 2; | ||
} else if (barThickness) { | ||
width = pos[length - 1] - pos[length - 2]; | ||
} else { | ||
width = minInterval; | ||
} | ||
right = Math.max(width / 2 - (1 - pos[length - 1]), 0); | ||
} | ||
} | ||
} | ||
|
||
|
@@ -643,7 +671,7 @@ module.exports = function() { | |
me._unit = timeOpts.unit || determineUnitForFormatting(ticks, timeOpts.minUnit, me.min, me.max); | ||
me._majorUnit = determineMajorUnit(me._unit); | ||
me._table = buildLookupTable(me._timestamps.data, min, max, options.distribution); | ||
me._offsets = computeOffsets(me._table, ticks, min, max, options); | ||
me._offsets = computeOffsets(me._table, ticks, me._timestamps.data, min, max, options); | ||
me._labelFormat = determineLabelFormat(me._timestamps.data, timeOpts); | ||
|
||
return ticksFromTimestamps(ticks, me._majorUnit); | ||
|
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.
This is getting a bit tricky to follow. I feel like we're trying to hack
prev
andnext
to get the desired results forstart
andsize
. I wonder if it would be easier if we just computed those directly like:Note that these formulas probably aren't at all correct. This is just to demonstrate an alternate way of laying out the code
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.
@benmccann your proposal introduces lot of code duplication and actually doesn't look clearer to me since it's hard to follow all the
if
/else
. The current implementation is not a "hack" of prev / next but an adjustment when they are not defined. Comments explain pretty well what's going on so please don't reformat this part of the code.