slider
slider copied to clipboard
there is a precision issue, when you set 'props.min' or 'props.max' as a float number.
<Slider
min={0.1}
max={2}
step={0.1}
value={this.state.zoom}
onChange={zoom => {
this.setState({ zoom });
}}
/>
screenshot:
Problem: max will never be 2, it forever only can be 1.9。
Let's View The Reason:
in this function, from this code: Math.floor((max - min) / step)
, number miss its precision.
// source code url: /src/utils.ts
export function getClosestPoint(val: number, { marks, step, min, max }) {
const points = Object.keys(marks).map(parseFloat);
if (step !== null) {
const maxSteps = Math.floor((max - min) / step); // from this line code, number miss its precision.
// calc steps:
// (max - min) / step => (2 - 0.1) / 0.1 = 18.999999999999996
// Math.floor((max - min) / step) => Math.floor(18.999999999999996) = 18
// maxSteps = 18
const steps = Math.min((val - min) / step, maxSteps);
// steps = 18
const closestStep = Math.round(steps) * step + min;
// Math.round(steps) * step + min => 18 * 0.1 + 0.1 = 1.9000000000000001
// closestStep = 1.9000000000000001
// so far, you will get closestStep value be: 1.9000000000000001, not 2
points.push(closestStep);
}
const diffs = points.map(point => Math.abs(val - point));
return points[diffs.indexOf(Math.min(...diffs))];
}
How to resolve this problem?
- adjust source code
- use integer number to avoid this precision problem.
const FixSlider = props => {
let {max, min, step = 1} = props;
max = max && max + step / 100;
min = min && min - step / 100;
return <Slider {...props} max={max} min={min}/>
}
<FixSlider
min={0.1}
max={2}
step={0.1}
value={this.state.zoom}
onChange={zoom => {
this.setState({ zoom });
}}
/>