在d3中创建一个反双曲正弦标度。js v4

时间:2022-09-28 13:36:59

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量表分为两个步骤:

  1. using the domain, deinterpolate the input given a deinterpolation function
  2. 使用定义域,在给定的定插值函数下对输入进行去插值
  3. using the range, interpolate the intermediate result from step 1 to obtain the output
  4. 使用范围,插入步骤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量表分为两个步骤:

  1. using the domain, deinterpolate the input given a deinterpolation function
  2. 使用定义域,在给定的定插值函数下对输入进行去插值
  3. using the range, interpolate the intermediate result from step 1 to obtain the output
  4. 使用范围,插入步骤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专家,所以我希望这能有所帮助。