-
Notifications
You must be signed in to change notification settings - Fork 12k
Improve offset calculation for scale.offset option #4658
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
Changes from all 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 |
---|---|---|
|
@@ -358,31 +358,67 @@ function generate(min, max, capacity, options) { | |
} | ||
|
||
/** | ||
* Returns the right and left offsets from edges in the form of {left, right}. | ||
* Returns the right and left offsets from the edges of the chart in the form of {left, right} | ||
* where each values is a relative width to the scale and ranges between 0 and 1. | ||
* They add extra margins on the both sides by scaling down the original scale. | ||
* Offsets are typically used for bar charts. They are calculated based on intervals | ||
* between the data points to keep the leftmost and rightmost bars from being cut. | ||
* 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; | ||
var i, ilen, curr, prev, length, width; | ||
|
||
if (!options.offset) { | ||
return {left: 0, right: 0}; | ||
} | ||
|
||
data.forEach(function(timestamp) { | ||
if (timestamp >= min && timestamp <= max) { | ||
pos.push(interpolate(table, 'time', timestamp, 'pos')); | ||
} | ||
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; | ||
}); | ||
|
||
length = pos.length; | ||
if (!length) { | ||
return {left: 0, right: 0}; | ||
} | ||
|
||
if (!barThickness) { | ||
// Calculate minInterval | ||
[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. actually I just thought of one last thing. can we move setting 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'm not sure what you mean. 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, you're right. Nevermind |
||
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); | ||
} | ||
|
||
return {left: left, right: right}; | ||
|
@@ -643,7 +679,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.