UNPKG

kepler.gl

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

173 lines (154 loc) 5.36 kB
// Copyright (c) 2018 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. import React, {Component} from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import styled from 'styled-components'; import SliderHandle from './slider-handle'; import SliderBarHandle from './slider-bar-handle'; function noop() {} const StyledRangeSlider = styled.div` position: relative; margin-bottom: 12px; background-color: ${props => props.theme.sliderBarBgd}; height: ${props => props.theme.sliderBarHeight}; `; const SliderWrapper = styled.div` flex-grow: 1; margin-top: ${props => props.isRanged ? 0 : 10}px; `; export default class Slider extends Component { static propTypes = { title: PropTypes.string, isRanged: PropTypes.bool, value0: PropTypes.number, value1: PropTypes.number, minValue: PropTypes.number, maxValue: PropTypes.number, sliderHandleWidth: PropTypes.number, onSlider0Change: PropTypes.func, onInput0Change: PropTypes.func, onSlider1Change: PropTypes.func, onInput1Change: PropTypes.func, onSliderBarChange: PropTypes.func, step: PropTypes.number, enableBarDrag: PropTypes.bool }; static defaultProps = { title: '', isRanged: true, value0: 0, value1: 100, minValue: 0, maxValue: 100, step: 1, sliderHandleWidth: 12, enableBarDrag: false, onSlider0Change: noop, onInput0Change: noop, onSlider1Change: noop, onInput1Change: noop, onSliderBarChange: noop, disabled: false }; ref = undefined; _saveRef = ref => { this.ref = ref; }; slide0Listener = x => { const xPercent = x / this.ref.offsetWidth; const maxDelta = this.props.maxValue - this.props.minValue; const val = xPercent * maxDelta; this.props.onSlider0Change.call(this, val + this.props.value0); }; slide1Listener = x => { const xPercent = x / this.ref.offsetWidth; const maxDelta = this.props.maxValue - this.props.minValue; const val = xPercent * maxDelta; this.props.onSlider1Change(val + this.props.value1); }; sliderBarListener = x => { const xPercent = x / this.ref.offsetWidth; const maxDelta = this.props.maxValue - this.props.minValue; const val = xPercent * maxDelta; const val0 = val + this.props.value0; const val1 = val + this.props.value1; this.props.onSliderBarChange(val0, val1); }; calcHandleLeft0 = (w, l, num) => { return w === 0 ? `calc(${l}% - ${this.props.sliderHandleWidth / 2}px)` : `calc(${l}% - ${this.props.sliderHandleWidth / 2}px)`; }; calcHandleLeft1 = (w, l) => { return this.props.isRanged && w === 0 ? `${l}%` : `calc(${l + w}% - ${this.props.sliderHandleWidth / 2}px)`; }; createSlider = (width, v0Left) => { return ( <div> <StyledRangeSlider className="kg-range-slider"> <SliderHandle className="kg-range-slider__handle" left={this.calcHandleLeft0(width, v0Left)} valueListener={this.slide0Listener} sliderHandleWidth={this.props.sliderHandleWidth} display={this.props.isRanged} /> <SliderHandle className="kg-range-slider__handle" left={this.calcHandleLeft1(width, v0Left)} valueListener={this.slide1Listener} sliderHandleWidth={this.props.sliderHandleWidth} /> <SliderBarHandle width={width} v0Left={v0Left} enableBarDrag={this.props.enableBarDrag} sliderBarListener={this.sliderBarListener} /> </StyledRangeSlider> </div> ); }; render() { const { classSet, isRanged, maxValue, minValue, value1 } = this.props; const value0 = !isRanged && minValue > 0 ? minValue : this.props.value0; const currValDelta = value1 - value0; const maxDelta = maxValue - minValue; const width = currValDelta / maxDelta * 100; const v0Left = (value0 - minValue) / maxDelta * 100; return ( <SliderWrapper className={classnames('kg-slider', {...classSet})} innerRef={this._saveRef} isRanged={isRanged} > {this.createSlider(width, v0Left)} </SliderWrapper> ); } }