To get the distribution you want, I think you can use this formula:
var value = Math.floor(-900 + 1000*Math.exp(i/10.857255959));
Here's a self-contained page that will print the values you'll get for your 0-100 slider, having passed them through that formula:
<html><body><script>
for (var i = 0; i <= 100; i++) {
var value = Math.floor(-900 + 1000*Math.exp(i/10.857255959));
document.write(value + "<br>");
}
</script></body></html>
The numbers go from 100 to 10,000,000 in what looks to my mathematically-rusty eye to be the distribution you want. 8-)
function logslider(position) {
// position will be between 0 and 100
var minp = 0;
var maxp = 100;
// The result should be between 100 an 10000000
var minv = Math.log(100);
var maxv = Math.log(10000000);
// calculate adjustment factor
var scale = (maxv-minv) / (maxp-minp);
return Math.exp(minv + scale*(position-minp));
}
The problem with a true Logarithmic slider is at the low end, multiple points on the slider will likely result in duplicate values.
From purely UI perspective, it also doesn't provide a very intuitive output for the users input.
I think a better option is to use an even-distribution "stepped" transform.
In other words, we specify a series of increments we want to use (ex: 1, 10, 100, 1000). Then we split the slider into equal parts based on the number of increments we defined. When we are sliding through our different sections, the slider output will increment by the respective increment.
We then must find the number of discrete values our slider must have so that it properly goes from min to max based on our defined interval distributions.
let sliderPoints = Math.ceil(
(max - min) /
intervals.reduce((total, interval) => total + interval / intervals.length, 0)
);
In this case 535.
Note: Your slider points should not exceed the number of pixels in the slider
Finally, we just transform our output using the algorithm described above. The code example also does some work so the output is always round for the the current step interval.
Here's a slightly different take with a pow() function. This allows setting a "skew" curve that governs the distribution of the input <-> output curve. Another refactored version allows setting the slider from logarithmic (exponential) input.
$(document).ready(function() {
$('#test').change(function() {
this.value = parseFloat(this.value).toFixed(2);
widthSliderCurve = this.value;
});
});
var widthSliderCurve = 0.42; // between -1 and 1 - governs the way the range is skewed
widthSlider.oninput = function() {
var thisSlider = document.getElementById("widthSlider");
var curve = Math.pow(10, widthSliderCurve); // convert linear scale into lograthimic exponent for other pow function
var originalMin = 1.0; // these are set in the slider defintion in HTML make sure they match!
var originalMax = 200.0; // these are set in the slider defintion in HTML
var mappedOutputMin = 0.05; // this is the desired output min
var mappedOutputMax = 10; // this is the desired output max
var originalRange = originalMax - originalMin;
var newRange = mappedOutputMax - mappedOutputMin;
var zeroRefCurVal = thisSlider.value - originalMin; // zero referenced
var normalizedCurVal = zeroRefCurVal / originalRange; // normalized to 0-1 output
var rangedValue = ((Math.pow(normalizedCurVal, curve) * newRange) + mappedOutputMin).toFixed(2);
var outbox = document.getElementById("wSliderOutput");
outbox.innerHTML = rangedValue;
//paper.tool.LineWidth = rangedValue;
};
let setLogSlider = function(value, widthSliderCurve, sliderType, outputName) {
/*** make sure constants match the oninput function values ***/
var curve = Math.pow(10, widthSliderCurve);
var originalMin = 1.0; // these are set in the slider defintion in HTML make sure they match!
var originalMax = 200.0; // these are set in the slider defintion in HTML
var mappedOutputMin = 0.05; // this is the desired output min
var mappedOutputMax = 10; // this is the desired output max
var originalRange = originalMax - originalMin;
var newRange = mappedOutputMax - mappedOutputMin;
var logToLinear = Math.pow((value - mappedOutputMin) / newRange, 1 / curve) * originalRange + originalMin;
console.log("logToLinear ", logToLinear);
// set the output box
var outbox = document.getElementById("wSliderOutput");
outbox.innerHTML = Number(value).toFixed(2);
// set the linear scale on the slider
document.querySelectorAll(".optionSliders").forEach((optSlider) => {
if (optSlider.getAttribute("data-slider-type") == sliderType) {
optSlider.value = logToLinear;
}
var outBox = document.getElementById(outputName);
outBox.value = value;
});
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<html>
<head>
<title>Pow function for variable skew of data mapping</title>
</head>
<body>
Enter a float between -1.0 and 1.0, hit return, and cycle the slider.</br>
<input id="test" type="text" value="0.5" />
<input id="widthSlider" sliderName="widthSlider" type="range" min="1" value="20" max="200" data-slider-type="linesWidth">
<label for="widthSlider">L Width <span id="Width">
<output id="wSliderOutput"></output>
</span></label>
</body>
</html>
var widthSliderCurve = 0.42; // between -1 and 1 - governs the way the range is skewed
widthSlider.oninput = function () {
var thisSlider = document.getElementById("widthSlider");
var curve = Math.pow(10, widthSliderCurve); // convert linear scale into lograthimic exponent for other pow function
var originalMin = 1.0; // these are set in the slider defintion in HTML make sure they match!
var originalMax = 200.0; // these are set in the slider defintion in HTML
var mappedOutputMin = 0.05; // this is the desired output min
var mappedOutputMax = 10; // this is the desired output max
var originalRange = originalMax - originalMin;
var newRange = mappedOutputMax - mappedOutputMin;
var zeroRefCurVal = thisSlider.value - originalMin; // zero referenced
var normalizedCurVal = zeroRefCurVal / originalRange; // normalized to 0-1 output
var rangedValue = ((Math.pow(normalizedCurVal, curve) * newRange) + mappedOutputMin).toFixed(2);
var outbox = document.getElementById("wSliderOutput");
outbox.innerHTML = rangedValue;
paper.tool.LineWidth = rangedValue;
//setLogSlider(rangedValue, widthSliderCurve, "L_Width", "wSliderOutput2");
};let setLogSlider = function (value, widthSliderCurve, sliderType, outputName){
/*** make sure constants match the oninput function values ***/
var curve = Math.pow(10, widthSliderCurve);
var originalMin = 1.0; // these are set in the slider defintion in HTML make sure they match!
var originalMax = 200.0; // these are set in the slider defintion in HTML
var mappedOutputMin = 0.05; // this is the desired output min
var mappedOutputMax = 10; // this is the desired output max
var originalRange = originalMax - originalMin;
var newRange = mappedOutputMax - mappedOutputMin;
var logToLinear = Math.pow((value - mappedOutputMin) / newRange, 1 / curve) * originalRange + originalMin;
console.log("logToLinear ", logToLinear);
// set the output box
var outbox = document.getElementById("wSliderOutput");
outbox.innerHTML = Number(value).toFixed(2);
// set the linear scale on the slider
document.querySelectorAll(".optionSliders").forEach((optSlider) => {
if (optSlider.getAttribute("data-slider-type") == sliderType) {
optSlider.value = logToLinear;
}
var outBox = document.getElementById(outputName);
outBox.value = value;
});
};
var widthSliderCurve = 0.42; // between -1 and 1 - governs the way the range is skewed
widthSlider.oninput = function () {
var thisSlider = document.getElementById("widthSlider");
var curve = Math.pow(10, widthSliderCurve); // convert linear scale into lograthimic exponent for other pow function
var originalMin = 1.0; // these are set in the slider defintion in HTML make sure they match!
var originalMax = 200.0; // these are set in the slider defintion in HTML
var mappedOutputMin = 0.05; // this is the desired output min
var mappedOutputMax = 10; // this is the desired output max
var originalRange = originalMax - originalMin;
var newRange = mappedOutputMax - mappedOutputMin;
var zeroRefCurVal = thisSlider.value - originalMin; // zero referenced
var normalizedCurVal = zeroRefCurVal / originalRange; // normalized to 0-1 output
var rangedValue = ((Math.pow(normalizedCurVal, curve) * newRange) + mappedOutputMin).toFixed(2);
var outbox = document.getElementById("wSliderOutput");
outbox.innerHTML = rangedValue;
paper.tool.LineWidth = rangedValue;