Javascript d3js-创建自定义比例-正对数和负对数
我目前正在从事一个d3项目,我正试图用一个大范围的数值来显示条形图,包括正数和负数 我在网上看到了一个使用Javascript d3js-创建自定义比例-正对数和负对数,javascript,d3.js,scale,logarithm,Javascript,D3.js,Scale,Logarithm,我目前正在从事一个d3项目,我正试图用一个大范围的数值来显示条形图,包括正数和负数 我在网上看到了一个使用d3.scale.sqrt()或显示两个对数刻度的演练,但我想知道是否可以创建自己的刻度 我想到的是负值的对数刻度,介于[-e,e]之间的值的线性刻度和正值的常规对数刻度之间的混合。 可能是这样的: y=-log(-x)如果x=1 | | x我找到了一个解决方案: 这可能是一种奇怪的方式,但我认为它是有效的,如果你有任何关于改进的建议,不要犹豫。我认为我犯了错误,特别是在日志基础和滴答声上
d3.scale.sqrt()
或显示两个对数刻度的演练,但我想知道是否可以创建自己的刻度
我想到的是负值的对数刻度,介于[-e,e]之间的值的线性刻度和正值的常规对数刻度之间的混合。
可能是这样的:
y=-log(-x)如果x<-e
y=x/e如果-e我发现了一个解决方案:
这可能是一种奇怪的方式,但我认为它是有效的,如果你有任何关于改进的建议,不要犹豫。我想我犯了错误,尤其是在原木底座和刻度上
这是我基于d3.js本身创建的函数
(function() {
scalepnlog = {
init: function(){
return d3_scale_pnlog(d3.scale.linear().domain([ 0, 1 ]), [ 1, 10 ]);
}
}
function d3_scaleExtent(domain) {
var start = domain[0], stop = domain[domain.length - 1];
return start < stop ? [ start, stop ] : [ stop, start ];
}
var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = {
floor: function(x) {
return -Math.ceil(-x);
},
ceil: function(x) {
return -Math.floor(-x);
}
};
function sign(x){
return x >= 0 ? 1:-1;
}
function d3_scale_pnlog(linear, domain) {
function pnlog(x) {
return (x >= Math.E || x <= -Math.E) ? sign(x)*Math.log(Math.abs(x)) : x/Math.E;
}
function pnpow(x) {
return (x >= 1 || x <= -1 )? sign(x)*Math.pow(Math.E,Math.abs(x)) : Math.E*x;
}
function scale(x) {
return linear(pnlog(x));
}
scale.invert = function(x) {
return pnpow(linear.invert(x));
};
scale.domain = function(x) {
if (!arguments.length) return domain;
linear.domain((domain = x.map(Number)).map(pnlog));
return scale;
};
scale.nice = function() {
var niced = d3_scale_nice(domain.map(pnlog), positive ? Math : d3_scale_logNiceNegative);
linear.domain(niced);
domain = niced.map(pow);
return scale;
};
scale.ticks = function() {
var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(pnlog(u)), j = Math.ceil(pnlog(v)), n = 10 % 1 ? 2 : 10;
if (isFinite(j - i)) {
for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pnpow(i) * k);
ticks.push(pnpow(i));
for (i = 0; ticks[i] < u; i++) {}
for (j = ticks.length; ticks[j - 1] > v; j--) {}
ticks = ticks.slice(i, j);
}
return ticks;
};
scale.tickFormat = function(n, format) {
if (!arguments.length) return d3_scale_logFormat;
if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format);
var k = Math.max(1, 10 * n / scale.ticks().length);
return function(d) {
var i = d / pnpow(Math.round(pnlog(d)));
if (i * 10 < 10 - .5) i *= 10;
return i <= k ? format(d) : "";
};
};
scale.copy = function() {
return d3_scale_pnlog(linear.copy(), domain);
};
return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
}
})();
及
功能pnpow(x){
return(x>=1 | | x我找到了一个解决方案:
这可能是一种奇怪的方式,但我认为它是有效的,如果你有任何关于改进的建议,不要犹豫。我认为我犯了错误,特别是在日志基础和滴答声上
这是我基于d3.js本身创建的函数
(function() {
scalepnlog = {
init: function(){
return d3_scale_pnlog(d3.scale.linear().domain([ 0, 1 ]), [ 1, 10 ]);
}
}
function d3_scaleExtent(domain) {
var start = domain[0], stop = domain[domain.length - 1];
return start < stop ? [ start, stop ] : [ stop, start ];
}
var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = {
floor: function(x) {
return -Math.ceil(-x);
},
ceil: function(x) {
return -Math.floor(-x);
}
};
function sign(x){
return x >= 0 ? 1:-1;
}
function d3_scale_pnlog(linear, domain) {
function pnlog(x) {
return (x >= Math.E || x <= -Math.E) ? sign(x)*Math.log(Math.abs(x)) : x/Math.E;
}
function pnpow(x) {
return (x >= 1 || x <= -1 )? sign(x)*Math.pow(Math.E,Math.abs(x)) : Math.E*x;
}
function scale(x) {
return linear(pnlog(x));
}
scale.invert = function(x) {
return pnpow(linear.invert(x));
};
scale.domain = function(x) {
if (!arguments.length) return domain;
linear.domain((domain = x.map(Number)).map(pnlog));
return scale;
};
scale.nice = function() {
var niced = d3_scale_nice(domain.map(pnlog), positive ? Math : d3_scale_logNiceNegative);
linear.domain(niced);
domain = niced.map(pow);
return scale;
};
scale.ticks = function() {
var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(pnlog(u)), j = Math.ceil(pnlog(v)), n = 10 % 1 ? 2 : 10;
if (isFinite(j - i)) {
for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pnpow(i) * k);
ticks.push(pnpow(i));
for (i = 0; ticks[i] < u; i++) {}
for (j = ticks.length; ticks[j - 1] > v; j--) {}
ticks = ticks.slice(i, j);
}
return ticks;
};
scale.tickFormat = function(n, format) {
if (!arguments.length) return d3_scale_logFormat;
if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format);
var k = Math.max(1, 10 * n / scale.ticks().length);
return function(d) {
var i = d / pnpow(Math.round(pnlog(d)));
if (i * 10 < 10 - .5) i *= 10;
return i <= k ? format(d) : "";
};
};
scale.copy = function() {
return d3_scale_pnlog(linear.copy(), domain);
};
return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
}
})();
及
功能pnpow(x){
返回(x>=1 | | x
function pnlog(x) {
return (x >= Math.E || x <= -Math.E) ? sign(x)*Math.log(Math.abs(x)) : x/Math.E;
}
function pnpow(x) {
return (x >= 1 || x <= -1 )? sign(x)*Math.pow(Math.E,Math.abs(x)) : Math.E*x;
}