This would be a replacement for a log scale so that it can deal with negative numbers. Haven't seen many examples of custom scales though I've been trying to use d3's logarithmic scale's source as a starting point.
As far as I know there are no ways to make custom scales in D3 (at least not in the sense you are looking for). All D3 scales scale in two steps:
I believe your ideal answer would basically answer the question, "how do I set a D3 scale's deinterpolation function to a custom function?", and I don't think this is currently possible.
However, you can set the interpolate function. This example from Mike Bostock shows how to set the interpolation using one of D3's built in ease functions: http://bl.ocks.org/mbostock/56ea94205411ee9e4dbec3742f7ad08c
That example kinda has a "fisheye lens" effect, which is probably the opposite of what you want. You can use the polynomial easing function, d3.easePolyInOut
, with an exponent less than one to get something closer to log scaling (see my code snippet). Unfortunately, there is no "logInOut" or "asinhInOut", so if you need a steeper rolloff (than polynomial), then you'll have to write your own easing/interpolation function.
var data = Array.from(Array(21), (_,i)=>{return 10*(i-10)})
var svg = d3.select("svg"),
margin = {top: 50, right: 20, bottom: 5, left: 20},
width = svg.attr("width") - margin.left - margin.right,
height = svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var polyexp = 0.25
var x = d3.scaleLinear()
.domain([-100,100])
.range([0, width])
.interpolate(easeInterpolate(d3.easePolyInOut.exponent(polyexp)));
g.append("g")
.attr("class", "axis axis--x")
.call(d3.axisBottom(x));
g.selectAll("circle").data(data).enter().append("circle")
.attr("cx", (d) => x(d))
.attr("cy", -10)
.attr("r", 3)
.attr("fill", "steelblue")
function easeInterpolate(ease) {
return function(a, b) {
var i = d3.interpolate(a, b);
return function(t) {
return i(ease(t));
};
};
}
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.js"></script>
<svg width="600" height="100"></svg>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With