sliderLineComponent.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import * as React from "react";
  2. import { Observable } from "babylonjs/Misc/observable";
  3. import { PropertyChangedEvent } from "../propertyChangedEvent";
  4. import { Tools } from 'babylonjs/Misc/tools';
  5. import { FloatLineComponent } from './floatLineComponent';
  6. interface ISliderLineComponentProps {
  7. label: string;
  8. target?: any;
  9. propertyName?: string;
  10. minimum: number;
  11. maximum: number;
  12. step: number;
  13. directValue?: number;
  14. useEuler?: boolean;
  15. onChange?: (value: number) => void;
  16. onInput?: (value: number) => void;
  17. onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
  18. decimalCount?: number;
  19. margin?: boolean;
  20. }
  21. export class SliderLineComponent extends React.Component<ISliderLineComponentProps, { value: number }> {
  22. private _localChange = false;
  23. constructor(props: ISliderLineComponentProps) {
  24. super(props);
  25. if (this.props.directValue !== undefined) {
  26. this.state = {
  27. value: this.props.directValue
  28. }
  29. } else {
  30. let value = this.props.target![this.props.propertyName!];
  31. if (value === undefined) {
  32. value = this.props.maximum;
  33. }
  34. this.state = { value: value };
  35. }
  36. }
  37. shouldComponentUpdate(nextProps: ISliderLineComponentProps, nextState: { value: number }) {
  38. if (nextProps.directValue !== undefined) {
  39. nextState.value = nextProps.directValue;
  40. return true;
  41. }
  42. let currentState = nextProps.target![nextProps.propertyName!];
  43. if (currentState === undefined) {
  44. currentState = nextProps.maximum;
  45. }
  46. if (currentState !== nextState.value || this._localChange || nextProps.maximum !== this.props.maximum || nextProps.minimum !== this.props.minimum) {
  47. nextState.value = currentState;
  48. this._localChange = false;
  49. return true;
  50. }
  51. return false;
  52. }
  53. onChange(newValueString: any) {
  54. this._localChange = true;
  55. let newValue = parseFloat(newValueString);
  56. if (this.props.useEuler) {
  57. newValue = Tools.ToRadians(newValue);
  58. }
  59. if (this.props.target) {
  60. if (this.props.onPropertyChangedObservable) {
  61. this.props.onPropertyChangedObservable.notifyObservers({
  62. object: this.props.target,
  63. property: this.props.propertyName!,
  64. value: newValue,
  65. initialValue: this.state.value
  66. });
  67. }
  68. this.props.target[this.props.propertyName!] = newValue;
  69. }
  70. if (this.props.onChange) {
  71. this.props.onChange(newValue);
  72. }
  73. this.setState({ value: newValue });
  74. }
  75. onInput(newValueString: any) {
  76. const newValue = parseFloat(newValueString);
  77. if (this.props.onInput) {
  78. this.props.onInput(newValue);
  79. }
  80. }
  81. prepareDataToRead(value: number) {
  82. if (value === null) {
  83. value = 0;
  84. }
  85. if (this.props.useEuler) {
  86. return Tools.ToDegrees(value);
  87. }
  88. return value;
  89. }
  90. render() {
  91. return (
  92. <div className="sliderLine">
  93. <div className={this.props.margin ? "label withMargins" : "label"} title={this.props.label}>
  94. {this.props.label}
  95. </div>
  96. <FloatLineComponent smallUI={true} label="" target={this.state} digits={this.props.decimalCount === undefined ? 4 : this.props.decimalCount} propertyName="value" min={this.props.minimum} max={this.props.maximum}
  97. onEnter={ () => {
  98. var changed = this.prepareDataToRead(this.state.value); this.onChange(changed);
  99. }
  100. }
  101. onChange={evt => {var changed = this.prepareDataToRead(this.state.value); this.onChange(changed)}} >
  102. </FloatLineComponent>
  103. <div className="slider">
  104. <input className="range" type="range" step={this.props.step} min={this.prepareDataToRead(this.props.minimum)} max={this.prepareDataToRead(this.props.maximum)} value={this.prepareDataToRead(this.state.value)}
  105. onInput={evt => this.onInput((evt.target as HTMLInputElement).value)}
  106. onChange={evt => this.onChange(evt.target.value)} />
  107. </div>
  108. </div>
  109. );
  110. }
  111. }