Range 区段选择器

如果项目中使用的是 0.x 版本的基础组件(@icedesign/base, @ali/ice, @alife/next),请在左侧导航顶部切换组件版本。

安装方法

  1. 在命令行中执行以下命令npm install @alifd/next@latest -S

开发指南

区间选择

何时使用

滑块控件(Sliders,简称滑块)可以让我们通过在连续或间断的区间内滑动锚点来选择一个合适的数值。区间最小值放在左边,对应的,最大值放在右边。滑块(Sliders)可以在滑动条的左右两端设定图标来反映数值的强度。这种交互特性使得它在设置诸如音量、亮度、色彩饱和度等需要反映强度等级的选项时成为一种极好的选择。

使用注意

  • onChange是和value进行配置做受控处理的。onChange在滑动过程中不会触发,滑动停止后会触发。

  • onProcess不建议内部做setState 进行受控,因为会频繁触发,整个滑动过程中会一直触发。

API

Range

参数说明类型默认值
slider滑块个数可选值:'single'(单个)'double'(两个)Enum'single'
min最小值Number0
max最大值Number100
step步长,取值必须大于 0,并且可被 (max - min) 整除。Number1
value设置当前取值。当 slidersingle 时,使用 Number,否则用 [Number, Number]Number/Array<Number>-
defaultValue设置初始取值。当 slidersingle 时,使用 Number,否则用 [Number, Number]Number/Array<Number>-
marks刻度数值显示逻辑(false 代表不显示,array 枚举显示的值,number 代表按 number 平分,object 表示按 key 划分,value 值显示)Boolean/Number/Array<Number>/Objectfalse
marksPositionmarks显示在上方('above')or下方('below')可选值:'above', 'below'Enum'above'
disabled值为 true 时,滑块为禁用状态Booleanfalse
onChange当 Range 的值发生改变后,会触发 onChange 事件,并把改变后的值作为参数传入, 如果设置了value, 要配合此函数做受控使用签名:Function(value: String/number) => void参数:value: {String/number} nullFunctionfunc.noop
onProcess滑块拖动的时候触发的事件,不建议在这里setState, 一般情况下不需要用, 滑动时有特殊需求时使用签名:Function(value: String/number) => void参数:value: {String/number} nullFunctionfunc.noop
hasTip是否显示 tipBooleantrue
tipRender自定义 tip 显示内容签名:Function(value: Number/String) => ReactNode参数:value: {Number/String} 值返回值:{ReactNode} 显示内容Functionvalue => value
reverse选中态反转Booleanfalse
pure是否pure renderBooleanfalse
fixedWidth是否为拖动线段类型,默认slider为double, defaultValue必传且指定区间Booleanfalse
tooltipVisibletooltip是否默认展示Booleanfalse
rtl是否已rtl模式展示Booleanfalse

ARIA and KeyBoard

按键说明
Right Arrow控制滑块往右移动
Left Arrow控制滑块向左移动
Tab切换滑动条

代码示例

基本

基本滑块,当 sliderdouble 时,渲染为双滑块。当 disabledtrue 时,滑块处于不可用状态。

Range 区段选择器 - 图1

查看源码在线预览

  1. import { Range } from '@alifd/next';
  2. const style = {
  3. marginBottom: '15px'
  4. };
  5. ReactDOM.render(<div style={{width: '400px', margin: '50px'}}>
  6. <h4>single slider - from left to right</h4>
  7. <Range defaultValue={30} style={style} hasTip={false} />
  8. <h4>single slider - from right to left</h4>
  9. <Range defaultValue={30} style={style} reverse hasTip={false} />
  10. <h4>double slider - from outside to inside</h4>
  11. <Range slider={'double'} defaultValue={[20, 40]} style={style} />
  12. <h4>double slider - from inside to outside</h4>
  13. <Range slider={'double'} defaultValue={[20, 40]} style={style} reverse />
  14. <h4>Disabled</h4>
  15. <Range defaultValue={30} disabled style={style} />
  16. <h4>Disabled</h4>
  17. <Range slider={'double'} defaultValue={[20, 40]} disabled style={style} />
  18. <h4>tooltipVisible disabled</h4>
  19. <Range disabled tooltipVisible defaultValue={60} style={style} />
  20. <h4>tooltipVisible</h4>
  21. <Range tooltipVisible defaultValue={60} style={style} />
  22. <h4>tooltipVisible disabled</h4>
  23. <Range disabled tooltipVisible slider={'double'} defaultValue={[57, 77]} style={style} />
  24. <h4>tooltipVisible</h4>
  25. <Range tooltipVisible slider={'double'} defaultValue={[57, 77]} style={style} />
  26. </div>, mountNode);

固定宽度滑动

默认双滑块(sliderdouble),且指定 defaultValue为区间值下可用。范围不可被改变,拖动所选区域改变始末滑块位置。

Range 区段选择器 - 图2

查看源码在线预览

  1. import { Range } from '@alifd/next';
  2. const style = {
  3. marginBottom: '15px'
  4. };
  5. const styleX3 = {
  6. marginBottom: '45px'
  7. };
  8. class App extends React.Component {
  9. constructor(props) {
  10. super(props);
  11. this.state = {
  12. value: [10, 300]
  13. };
  14. }
  15. //Controlled. onChange will be triggered when startValue isn't equal to endValue after sliding
  16. onChange(value) {
  17. console.log('onChange value:', value);
  18. this.setState({value});
  19. }
  20. // This callback will be triggered when startValue and endValue aren't equal after mousedown/mousemove. You shouldn't call setState here.
  21. onProcess(value) {
  22. // this.setState({value});
  23. console.log('onProcess: ', value);
  24. }
  25. render() {
  26. return (
  27. <div style={{width: '400px', margin: '50px'}}>
  28. <h4>fixedWidth basic</h4>
  29. <Range fixedWidth defaultValue={[20, 40]} style={style} />
  30. <h4>fixedWidth basic with tooltipVisible</h4>
  31. <Range tooltipVisible fixedWidth defaultValue={[70, 90]} style={styleX3} />
  32. <Range disabled tooltipVisible fixedWidth defaultValue={[70, 90]} style={style} />
  33. <h4>fixedWidth with marks</h4>
  34. <Range fixedWidth step={10} defaultValue={[20, 40]} scales={10} marks={10} style={styleX3} />
  35. <Range fixedWidth step={2} defaultValue={[60, 80]} scales={[0, 100]} marks={[0, 30, 100]} style={style} marksPosition="below" />
  36. <h4>fixedWidth with 0.01 step</h4>
  37. <Range fixedWidth defaultValue={[0.6, 0.7]} min={0.5} max={1} step={0.01}/>
  38. <div style={{width: '400px', marginTop: '50px'}}>
  39. <p>range 0 ~ 1024</p>
  40. <Range fixedWidth value={this.state.value}
  41. onChange={this.onChange.bind(this)}
  42. onProcess={this.onProcess.bind(this)}
  43. min={0} max={1024} marks={[0, 1024]} />
  44. </div>
  45. </div>
  46. );
  47. }
  48. }
  49. ReactDOM.render(<App />, mountNode);

刻度及标识

通过 scalesmarks 属性设置刻度及标识。

Range 区段选择器 - 图3

查看源码在线预览

  1. import { Range } from '@alifd/next';
  2. const style = {
  3. marginBottom: '20px',
  4. marginTop: '20px'
  5. };
  6. ReactDOM.render(<div style={{width: '400px', margin: '50px'}}>
  7. <p>With minimal and maximal value</p>
  8. <Range defaultValue={0} marks={[0, 100]} style={style} />
  9. <Range slider={'double'} defaultValue={[20, 40]} scales={[0, 100]} marks={[0, 100]} style={style} />
  10. <Range defaultValue={30} style={style} />
  11. <p>Below</p>
  12. <Range defaultValue={0} marks={[0, 100]} style={style} marksPosition="below" />
  13. <Range slider={'double'} defaultValue={[20, 40]} scales={[0, 100]} marks={[0, 100]} style={style} marksPosition="below" />
  14. <Range defaultValue={30} scales={[0, 100]} marks={[0, 100]} style={style} marksPosition="below" />
  15. <p>Equal division</p>
  16. <Range defaultValue={30} marks={5} style={style} />
  17. <Range slider={'double'} defaultValue={[20, 40]} scales={10} marks={10} style={style} />
  18. <Range disabled slider={'double'} defaultValue={[20, 40]} scales={10} marks={10} style={style} />
  19. <p>Free</p>
  20. <Range defaultValue={30} marks={[0, 26, 37, 100]} style={style} />
  21. <Range slider={'double'} defaultValue={[20, 40]} marks={[0, 26, 37, 100]} style={style} hasTip={false}/>
  22. <Range defaultValue={30} marks={{0: '0°C', 26: '26°C', 37: '37°C', 100: '100°C'}} style={style} />
  23. </div>, mountNode);

min,max,step

可以通过 minmax 设置范围边界。通过 step(被 max - min 整除) 设置移动的最小步频。min默认为0,max默认为100.

Range 区段选择器 - 图4

查看源码在线预览

  1. import { Range } from '@alifd/next';
  2. const style = {
  3. marginBottom: '40px',
  4. marginTop: '40px'
  5. };
  6. ReactDOM.render(
  7. <div style={{width: '400px', margin: '50px'}}>
  8. <p>Range 0 ~ 1024</p>
  9. <Range defaultValue={128} min={0} max={1024} marks={[0, 1024]} style={style} />
  10. <p>Range 0 ~ 1024step 128</p>
  11. <Range defaultValue={512} min={0} max={1024} step={128} marks={[0, 1024]}
  12. style={style} />
  13. </div>
  14. , mountNode);

事件

onChange,onProcess事件

Range 区段选择器 - 图5

查看源码在线预览

  1. import { Range } from '@alifd/next';
  2. class App extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. value: 128,
  7. value2: 300,
  8. doubleValue: [200, 300]
  9. };
  10. }
  11. //Controlled. onChange will be triggered when startValue isn't equal to endValue after sliding
  12. onChange(value) {
  13. console.log('onChange value:', value);
  14. this.setState({value});
  15. }
  16. // This callback will be triggered when startValue and endValue aren't equal after mousedown/mousemove. You shouldn't call setState here.
  17. onProcess(value) {
  18. console.log('onProcess: ', value);
  19. }
  20. onChangeDouble(doubleValue) {
  21. console.log('onChange doubleValue:', doubleValue);
  22. this.setState({doubleValue});
  23. }
  24. onProcessDouble(doubleValue) {
  25. console.log('onProcess: ', doubleValue);
  26. }
  27. render() {
  28. return (
  29. <div style={{width: '400px', margin: '50px'}}>
  30. <p>range 0 ~ 1024</p>
  31. <div style={{width: '400px', marginTop: '50px'}}>
  32. <Range value={this.state.value} onChange={this.onChange.bind(this)}
  33. onProcess={this.onProcess.bind(this)}
  34. min={0} max={1024} marks={[0, 1024]} />
  35. </div>
  36. <p>with value and without onChange</p>
  37. <div style={{width: '400px', marginTop: '50px'}}>
  38. <Range value={this.state.value2}
  39. onProcess={this.onProcess.bind(this)}
  40. min={0} max={1024} marks={[0, 1024]} />
  41. </div>
  42. <p>double slider controlled</p>
  43. <div style={{width: '400px', marginTop: '50px'}}>
  44. <Range slider="double" value={this.state.doubleValue} onChange={this.onChangeDouble.bind(this)}
  45. onProcess={this.onProcessDouble.bind(this)}
  46. min={0} max={1024} marks={[0, 1024]} />
  47. </div>
  48. </div>
  49. );
  50. }
  51. }
  52. ReactDOM.render(<App />, mountNode);

范围与 step

与number-picker结合,外部控制,与Icon结合设置边界Icon

Range 区段选择器 - 图6

查看源码在线预览

  1. import { Range, NumberPicker, Grid, Icon } from '@alifd/next';
  2. const {Row, Col} = Grid;
  3. class Demo extends React.Component {
  4. constructor(props, context) {
  5. super(props, context);
  6. this.state = {
  7. valueInt: 3,
  8. valueDec: 0.05,
  9. valueIcon: 1,
  10. preIconClass: '',
  11. afterIconClass: ''
  12. };
  13. }
  14. onChangeInt(value) {
  15. console.log(value);
  16. this.setState(Object.assign({}, this.state, {
  17. valueInt: value
  18. }));
  19. }
  20. onChangeDec(value) {
  21. this.setState(Object.assign({}, this.state, {
  22. valueDec: value
  23. }));
  24. }
  25. onIconRangeProcess(value) {
  26. const mid = 50;
  27. this.setState(Object.assign({}, this.state, {
  28. valueIcon: value,
  29. preIconClass: value < mid ? 'myicon-highlight' : '',
  30. afterIconClass: value >= mid ? 'myicon-highlight' : ''
  31. }));
  32. }
  33. render() {
  34. return (
  35. <div style={{width: '400px', margin: '50px'}}>
  36. <h2>Used with numberPicker</h2>
  37. <Row>
  38. <Col span="12" style={{marginTop: '10px'}}>
  39. <Range value={this.state.valueInt} min={0} max={20} step={1}
  40. onChange={this.onChangeInt.bind(this)} />
  41. </Col>
  42. <Col span="12">
  43. <NumberPicker value={this.state.valueInt} min={0} max={1024} step={1}
  44. onChange={this.onChangeInt.bind(this)} />
  45. </Col>
  46. </Row>
  47. <br />
  48. <Row>
  49. <Col span="12" style={{marginTop: '10px'}}>
  50. <Range value={this.state.valueDec} min={0} max={1} step={0.01}
  51. onChange={this.onChangeDec.bind(this)} />
  52. </Col>
  53. <Col span="12">
  54. <NumberPicker value={this.state.valueDec} min={0} max={1} step={0.01}
  55. onChange={this.onChangeDec.bind(this)} />
  56. </Col>
  57. </Row>
  58. <h2>Used with Icon</h2>
  59. <div className="iconWrapper">
  60. <Icon className={`myicon ${this.state.preIconClass}`} type="cry" />
  61. <Range min={1} max={100} onChange={this.onIconRangeProcess.bind(this)} value={this.state.valueIcon} />
  62. <Icon className={`myicon ${this.state.afterIconClass}`} type="smile" />
  63. </div>
  64. </div>
  65. );
  66. }
  67. }
  68. ReactDOM.render(<Demo />, mountNode);
  1. .iconWrapper {
  2. position: relative;
  3. padding: 0px 40px;
  4. }
  5. .iconWrapper .myicon {
  6. position: absolute;
  7. top: -3px;
  8. width: 16px;
  9. height: 16px;
  10. line-height: 1;
  11. font-size: 16px;
  12. color: #ccc;
  13. }
  14. .iconWrapper .myicon:first-child {
  15. left: 0;
  16. }
  17. .iconWrapper .myicon:last-child {
  18. right: 0;
  19. }
  20. .myicon.myicon-highlight {
  21. color: #666;
  22. }

tipRender

tipRender 示例

Range 区段选择器 - 图7

查看源码在线预览

  1. import { Range } from '@alifd/next';
  2. class App extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. value: 128
  7. };
  8. }
  9. // This callback will be triggered when startValue and endValue aren't equal after moving.
  10. onChange(value) {
  11. console.log('onChange value:', value);
  12. }
  13. // This callback will be triggered when startValue and endValue aren't equal after mousedown/mousemove. You can call setState here when using a controlled component.
  14. onProcess(value) {
  15. console.log('onProcess');
  16. this.setState({value});
  17. }
  18. formatter(value) {
  19. return `$${value}`;
  20. }
  21. render() {
  22. return (
  23. <div style={{width: '400px', margin: '50px'}}>
  24. <p>Range 0 ~ 1024</p>
  25. <div style={{width: '400px', marginTop: '50px'}}>
  26. <Range defaultValue={256} tipRender={this.formatter.bind(this)} value={this.state.value} onChange={this.onChange.bind(this)}
  27. onProcess={this.onProcess.bind(this)}
  28. min={0} max={1024} marks={[0, 1024]} />
  29. </div>
  30. </div>
  31. );
  32. }
  33. }
  34. ReactDOM.render(<App />, mountNode);

选择态反转

设置reverse为true, 选中态会反转。

Range 区段选择器 - 图8

查看源码在线预览

  1. import { Range } from '@alifd/next';
  2. const style = {
  3. marginBottom: '15px'
  4. };
  5. ReactDOM.render(
  6. <div style={{width: '400px', margin: '50px'}}>
  7. <Range defaultValue={30} style={style} hasTip={false} />
  8. <Range defaultValue={30} style={style} reverse hasTip={false} />
  9. <Range slider={'double'} defaultValue={[20, 40]} style={style} />
  10. <Range slider={'double'} defaultValue={[20, 40]} style={style} reverse />
  11. <Range defaultValue={30} disabled style={style} />
  12. <Range defaultValue={30} disabled style={style} reverse />
  13. <Range slider={'double'} defaultValue={[20, 40]} disabled style={style} />
  14. <Range slider={'double'} defaultValue={[20, 40]} disabled style={style} reverse />
  15. </div>, mountNode);

无障碍

通过Tab键或其他方式使滑块被聚焦之后,可以通过按下键盘的左右箭头来改变滑块的位置,目前只有单滑块支持无障碍。

Range 区段选择器 - 图9

查看源码在线预览

  1. import { Range } from '@alifd/next';
  2. const style = {
  3. marginBottom: '15px'
  4. };
  5. ReactDOM.render(<div style={{width: '400px', margin: '50px'}}>
  6. <h4>single slider - from left to right</h4>
  7. <Range defaultValue={30} style={style} hasTip={false} />
  8. <h4>single slider - from right to left</h4>
  9. <Range defaultValue={30} style={style} reverse hasTip={false} />
  10. </div>, mountNode);

相关区块

Range 区段选择器 - 图10

暂无相关区块