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.
这将替代对数标度,以便它可以处理负数。我还没有见过很多自定义比例的例子,但是我一直在尝试使用d3的对数比例的来源作为起点。
2 个解决方案
#1
7
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:
据我所知,在D3中没有办法使自定义尺度(至少在你所寻找的意义上没有)。所有D3量表分为两个步骤:
- using the domain, deinterpolate the input given a deinterpolation function
- 使用定义域,在给定的定插值函数下对输入进行去插值
- using the range, interpolate the intermediate result from step 1 to obtain the output
- 使用范围,插入步骤1的中间结果以获得输出
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.
我相信你的理想答案基本上可以回答这个问题:“我如何将D3标度的去插函数设置为自定义函数?”我认为这是不可能的。
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
但是,您可以设置插值函数。这个来自Mike Bostock的示例展示了如何使用D3内置的ease函数之一来设置插值: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.
这个例子有一个“鱼眼镜头”效应,这可能与你想要的相反。你可以用多项式缓动函数d3。easePolyInOut,其指数小于1,以获得更接近日志扩展(请参阅我的代码片段)。不幸的是,没有“注销”或“asinhInOut”,所以如果需要更陡的滚动(而不是多项式),那么您必须编写自己的缓动/内插函数。
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>
#2
-3
The best example in the documentation seems to be the interpolate feature of a scale. See https://github.com/d3/d3-scale/blob/master/README.md#continuous-scales
文档中最好的例子似乎是规模的内插特性。看到https://github.com/d3/d3-scale/blob/master/README.md continuous-scales
var color = d3.scaleLinear()
.domain([10, 100])
.range(["brown", "steelblue"])
.interpolate(d3.interpolateHcl);
I'm not really a d3 expert so I hope that helps.
我不是真正的d3专家,所以我希望这能有所帮助。
#1
7
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:
据我所知,在D3中没有办法使自定义尺度(至少在你所寻找的意义上没有)。所有D3量表分为两个步骤:
- using the domain, deinterpolate the input given a deinterpolation function
- 使用定义域,在给定的定插值函数下对输入进行去插值
- using the range, interpolate the intermediate result from step 1 to obtain the output
- 使用范围,插入步骤1的中间结果以获得输出
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.
我相信你的理想答案基本上可以回答这个问题:“我如何将D3标度的去插函数设置为自定义函数?”我认为这是不可能的。
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
但是,您可以设置插值函数。这个来自Mike Bostock的示例展示了如何使用D3内置的ease函数之一来设置插值: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.
这个例子有一个“鱼眼镜头”效应,这可能与你想要的相反。你可以用多项式缓动函数d3。easePolyInOut,其指数小于1,以获得更接近日志扩展(请参阅我的代码片段)。不幸的是,没有“注销”或“asinhInOut”,所以如果需要更陡的滚动(而不是多项式),那么您必须编写自己的缓动/内插函数。
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>
#2
-3
The best example in the documentation seems to be the interpolate feature of a scale. See https://github.com/d3/d3-scale/blob/master/README.md#continuous-scales
文档中最好的例子似乎是规模的内插特性。看到https://github.com/d3/d3-scale/blob/master/README.md continuous-scales
var color = d3.scaleLinear()
.domain([10, 100])
.range(["brown", "steelblue"])
.interpolate(d3.interpolateHcl);
I'm not really a d3 expert so I hope that helps.
我不是真正的d3专家,所以我希望这能有所帮助。