react native 滑动价格区间(step 支持一格移动大小)

image.png

import React, { Component } from 'react'
import { StyleSheet, View, PanResponder, Text, Dimensions } from 'react-native'

const roundSize = 30  // 圆的大小
const width = Dimensions.get('window').width - roundSize * 1.5 // 设备宽度

/**
 * 价格区间
 */
export default class PriceRange extends Component {
  constructor(props) {
    super(props)
    let scale = width / this.props.range
    let { range, startPrice, endPrice } = this.props
    let start = startPrice === 0 ? roundSize / 2 : scale * startPrice
    let end = endPrice === '不限' ? width : scale * endPrice
    this.state = {
      range,
      startPrice,
      endPrice,
      start, // 起始坐标
      end, // 结束坐标
    }
  }

  componentWillReceiveProps(nextProps) {
    let scale = width / this.props.range
    let { range, startPrice, endPrice } = nextProps
    let start = startPrice === 0 ? roundSize / 2 : (startPrice===range ? width-20 : scale * startPrice)
    let end = endPrice === '不限' ? width : scale * endPrice
    this.setState({
      range,
      startPrice,
      endPrice,
      start, // 起始坐标
      end, // 结束坐标
    })
  }

  componentWillMount() {
    let scale = width / this.props.range
    let step  = this.props.step * scale
    this.panResponderStart = PanResponder.create({
      onStartShouldSetPanResponder: (evt, gestureState) => true,
      onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
      onMoveShouldSetPanResponder: (evt, gestureState) => true,
      onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
      onPanResponderTerminationRequest: (evt, gestureState) => true,
      onPanResponderGrant: (evt, gestureState) => {
        this.forceUpdate()
      },
      onPanResponderMove: (evt, gestureState) => { // 开始的拖动事件
        let start = gestureState.moveX // 当前拖动所在的坐标
        let threshold = this.state.end - roundSize // 阀值
        if (start >= threshold) {  // 保证开始价格不会超过结束价格
          start = threshold
        }

        start = parseInt(start / step) * step
        let startPrice = Math.floor(start / scale) // 计算开始价格显示值
        if (start <= roundSize) { // 保证开始价格不会小于最小值
          start = roundSize / 2
          startPrice = 0
        }

        this.setState({
          start,
          startPrice
        }, () => {
          this.props.onChange(this.state.startPrice, this.state.endPrice)
        })
      },
      onPanResponderRelease: (evt, gestureState) => true,
      onPanResponderTerminate: (evt, gestureState) => true,
    })
    this.panResponderEnd = PanResponder.create({
      onStartShouldSetPanResponder: (evt, gestureState) => true,
      onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
      onMoveShouldSetPanResponder: (evt, gestureState) => true,
      onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
      onPanResponderTerminationRequest: (evt, gestureState) => true,
      onPanResponderGrant: (evt, gestureState) => {
        this.forceUpdate()
      },
      onPanResponderMove: (evt, gestureState) => { // 结束的拖动事件
        let end = gestureState.moveX
        let threshold = this.state.start + roundSize // 阀值
        if (end <= threshold) {  // 保证开始价格不会超过结束价格
          end = threshold
        }

        end = parseInt(end / step) * step

        let endPrice = Math.floor(end / scale)
        if (end >= width) { // 保证结束价格不会超过最大值
          end = width
          endPrice = '不限'
        }
        this.setState({
          end,
          endPrice
        }, () => {
          this.props.onChange(this.state.startPrice, this.state.endPrice)
        })
      },
      onPanResponderRelease: (evt, gestureState) => true,
      onPanResponderTerminate: (evt, gestureState) => true,
    })
  }

  render() {
    let { start, end, startPrice, endPrice, range } = this.state
    return (
      <View style={styles.container}>
        <View style={[{ position: 'absolute' }, { left: startPrice===range ? roundSize/2 : start }, { top: -3 }]}><Text style={{color:'#6D7096'}}>{`¥${startPrice}`}</Text></View>
        <View style={[{ position: 'absolute' }, { left: startPrice===range || endPrice===range ? width-20 : end }, { top: -3 }]}><Text style={{color:'#6D7096'}}>{endPrice !== '不限' ? `¥${endPrice}` : (startPrice===range ? `¥${startPrice}+`:endPrice)}</Text></View>
        <View style={{ flexDirection: 'row' }}>
          <View style={[styles.progressContainer, { backgroundColor: '#D6D7E6' }, { width: start }]}></View>
          <View style={[styles.progressContainer, { width: width - start - (width - end) }]}></View>
          <View style={[styles.progressContainer, { backgroundColor: '#D6D7E6' }, { width: width - end }]}></View>
        </View>
        <View style={[styles.circle, { left: start }]} {...this.panResponderStart.panHandlers}>
        </View>
        <View style={[styles.circle, { left: end }]} {...this.panResponderEnd.panHandlers}>
        </View>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    height: 70,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#fff'
  },
  progressContainer: {
    backgroundColor: '#ffa710',
    height: 4
  },
  circle: {
    position: 'absolute',
    width: roundSize,
    height: roundSize,
    borderRadius: roundSize / 2,
    borderColor: '#D6D7E6',
    borderWidth: 1,
    shadowColor: 'rgba(0,0,0,0.6)',
    shadowRadius: 5,
    shadowOpacity: 0.9,
    backgroundColor: '#f8f8fe'
  }
})

PriceRange.defaultProps = {
  range: 1000, // 价格范围
  startPrice: 0, // 起始价格
  endPrice: '不限', // 结束价格
  step: 50, // 一格大小
  onChange: function() {} // 回调
}

用法

// 回调
onChange(start, end) {
    this.setState({
      start,
      end
    })
}

<PriceRange range={1000} startPrice={this.state.start} endPrice={ this.state.end === 0 ? '



作者:tomorrow_chen
链接:https://www.jianshu.com/p/d57805d1496c
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
<head>     <meta charset="UTF-8">     <title>价格滑动效果  </title>     <link rel="stylesheet" href="css/style.css?3.1.64"> </head> <body 100px;"> <!--价格筛选条开始--> <div class="price-dd-choose">     <div id="price-range" class="price-range">         <div class="price-range-slider">             <div class="bg-darkgrey"></div>             <div class="bg-darkgrey-hand"></div>             <ul class="slider-ul">                 <li class="slider-ul-first"><i class="icon-dian"></i></li>                 <li><i class="icon-dian"></i></li>                 <li><i class="icon-dian"></i></li>                 <li><i class="icon-dian"></i></li>                 <li><i class="icon-dian"></i></li>                 <li><i class="icon-dian"></i></li>                 <li><i class="icon-dian"></i></li>                 <li><i class="icon-dian"></i></li>                 <li><i class="icon-dian"></i></li>                 <li><i class="icon-dian"></i></li>             </ul>         </div>         <div class="slide-selected"></div>         <i class="btn-price btn-left"></i>         <i class="btn-price btn-right"></i>         <div class="tip">             <div class="tip-content"></div>             <span class="tip-top tip-arrow"></span>         </div>         <div class="price-range-text">             <span class="number number-first">0万</span><span class="number">5万</span><span class="number">10万</span><span class="number">15万</span><span class="number">20万</span><span class="number">25万</span><span class="number">30万</span><span class="number">35万</span><span class="number">50万</span><span class="number">70万</span><span class="number">100万</span>         </div>     </div> </div> 这是一个CSS3的价格区间拖动滑动特效,有需要的朋友可以直接下载使用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值