-
Notifications
You must be signed in to change notification settings - Fork 286
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
Pad domain addition? #150
Comments
In case it is helpful, we implemented this functionality in Vega for various scale types (symlog coming soon):
|
I like this idea—I needed something similar in this recent scatterplot. I ended up doing a little transformation of the domain: function padLinear([x0, x1], k) {
const dx = (x1 - x0) * k / 2;
return [x0 - dx, x1 + dx];
} y = d3.scaleLinear()
.domain(padLinear(d3.extent(data.flatMap(d => [d.R90_10_1980, d.R90_10_2015])), 0.1))
.rangeRound([height - margin.bottom, margin.top]) I can see it being nice to specify the padding in pixel space rather than as a proportion, though. |
+1 for this -- both in pixel space and as a proportion. It would also be nice to be able to pad asymmetrically. |
I'll take a crack at this as a PR for d3-scale using the Vega setup as a jumping off point. It will need to be modified to pad the min and the max separately. I think this would be good to include as a part of d3-scale instead of building into outside libraries since there's not a simple way to distinguish between all the different types of scales and what transform function you'd need to use. |
+1! adding a padding in pixels to scales could be very useful. |
IMO it might be nice to just expose that This one: export function padLinear([x0, x1], k) {
const dx = (x1 - x0) * k / 2;
return [x0 - dx, x1 + dx];
} It's nice that it is isolated, not required to be a method on scales. For the pixels case, This would set a precedent and open the door for subtle implementations for other scale types, like |
I started a PR for Please let me know if this looks like a good direction. With some encouragement I'm happy to flesh out the PR with README updates - but first I want to confirm this direction is acceptable. Thanks for reviewing! |
Related for map projections: d3/d3-geo#162 —in which the padding is named "inset" and not divided by 2. |
My original implementation was a bit off but this is now properly implemented in LayerCake with the Vega transform helpers so that it works on log and power scales, too. You supply the padding you want in pixels for either the min or the max. I most likely won't have the bandwidth to do a d3-scale PR for this but someone should feel free to if they want. |
Very cool! If anyone wants to branch from my PR #213 and add the implementation for log and power scales, go for it! |
Stepping back a bit, could the same fundamental problem be solved instead by drawing the axes differently? For example, offsetting the tick labels, and drawing grid/domain lines such that they are slightly removed from the points that fall exactly on the min/max of the domain? Maybe with a technique like that this whole problem could be sidestepped. |
EDIT Nevermind, I think I figured it out. Will post it here for anyone who needs to pad a logarithmic scale with a specific amount of pixels.
Can someone shed light on the math of adding padding to a logarithmic scale? 😕 |
I run into the original problem when I have a scatter plot where I'm sizing the radius of the circle by a value in the data. To handle dots of varying diameter, I'm not sure if there's a way around calculating how much space the largest circle needs in order to not overlap with the axis lines – since it's not just about the points that fall exactly on the line. The issue is having that buffer space in the design. |
Here's a quick demo of how one might move the axes to make space for the marks. svg
.append('g')
.attr('transform', `translate(${margin.left},0)`)
.call(axisLeft(y));
svg
.append('g')
.attr(
'transform',
`translate(0,${height - margin.bottom})`
)
.call(axisBottom(x)); const axisPadding = 7;
...
svg
.append('g')
.attr('transform', `translate(${margin.left - axisPadding},0)`)
.call(axisLeft(y));
svg
.append('g')
.attr(
'transform',
`translate(0,${height - margin.bottom + axisPadding})`
)
.call(axisBottom(x)); |
I think that could definitely work for some folks – great to have put it together! I know for my use case, it may be a little tricky if you have different charts on a page with different y-axis alignments, especially if you end up with a radius that's quite bit, such as >25 pixels. I was able to sort this out as post-scale transformation so whatever you think is best from a library perspective is fine. |
Add padding to x-axis by padding the domain of the xScale. Copied the example shared in open issue to support this natively in d3-scale <d3/d3-scale#150 (comment)>
Add padding to x-axis by padding the domain of the xScale. Copied the example shared in open issue to support this natively in d3-scale <d3/d3-scale#150 (comment)>
When I'm making scatter plots (and others), I find myself padding the scale's domain by the pixel radius of my circles to avoid them overlapping with the y-axis. I specify the number of pixels I want to increase on the left and right side of the domain, use the scale's inverse to add or subtract that amount from the domain and use that result to reset it.
I made a convenience function to do this and was curious if you would want a PR if this seems like useful functionality.
The api could be something like:
[edited for better order of operations in the API example]
The text was updated successfully, but these errors were encountered: