欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

ReactNative實(shí)現(xiàn)弧形拖動(dòng)條的代碼案例

 更新時(shí)間:2024年02月05日 11:17:44   作者:xvzhengyang  
本文介紹了ReactNative實(shí)現(xiàn)弧形拖動(dòng)條,本組件使用到了react-native-svg和PanResponder,結(jié)合示例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

我們直接看效果

先看下面的使用代碼

     <CircularSlider5
          step={2}
          min={0}
          max={100}
          radius={100}
          value={30}
          onComplete={(changeValue: number) => this.handleEmailSbp(changeValue)}
          onChange={(changeValue: number) => this.handleEmailDpd(changeValue)}
          contentContainerStyle={styles.contentContainerStyle}
          strokeWidth={10}
          buttonBorderColor="#3FE3EB"
          buttonFillColor="#fff"
          buttonStrokeWidth={10}
          openingRadian={Math.PI / 4}
          buttonRadius={10}
          triangleLinerGradient={[
            {stop: '0%', color: '#FF7B4C'},
            {stop: '50%', color: '#FFFFFF'},
            {stop: '100%', color: '#317AF7'},
          ]}
          linearGradient={[
            {stop: '0%', color: '#3FE3EB'},
            {stop: '100%', color: '#7E84ED'},
          ]}></CircularSlider5>
           {
    radius: 100, // 半徑
    strokeWidth: 20, // 線寬
    openingRadian: Math.PI / 4, // 開口弧度,為了便于計(jì)算值為實(shí)際開口弧度的一半
    backgroundTrackColor: '#e8e8e8', // 底部軌道顏色
    linearGradient: [
      {stop: '0%', color: '#1890ff'},
      {stop: '100%', color: '#f5222d'},
    ], // 漸變色
    min: 0, // 最小值
    max: 100, // 最大值
    buttonRadius: 12, // 按鈕半徑
    buttonBorderColor: '#fff', // 按鈕邊框顏色
    buttonStrokeWidth: 1, // 按鈕線寬
  };

本組件使用到了

1.react-native-svg

2.PanResponder

具體代碼如下

import React, {PureComponent} from 'react';
import Svg, {
  Path,
  G,
  Defs,
  LinearGradient,
  Stop,
  Circle,
} from 'react-native-svg';
import {StyleSheet, View, PanResponder} from 'react-native';
export default class CircularSlider extends PureComponent {
  static defaultProps = {
    radius: 100, // 半徑
    strokeWidth: 20, // 線寬
    openingRadian: Math.PI / 4, // 開口弧度,為了便于計(jì)算值為實(shí)際開口弧度的一半
    backgroundTrackColor: '#e8e8e8', // 底部軌道顏色
    linearGradient: [
      {stop: '0%', color: '#1890ff'},
      {stop: '100%', color: '#f5222d'},
    ], // 漸變色
    min: 0, // 最小值
    max: 100, // 最大值
    buttonRadius: 12, // 按鈕半徑
    buttonBorderColor: '#fff', // 按鈕邊框顏色
    buttonStrokeWidth: 1, // 按鈕線寬
  };
  constructor(props) {
    super(props);
    this._panResponder = PanResponder.create({
      onStartShouldSetPanResponder: () => true,
      onMoveShouldSetPanResponder: () => false,
      onPanResponderGrant: this._handlePanResponderGrant,
      onPanResponderMove: this._handlePanResponderMove,
      onPanResponderRelease: this._handlePanResponderEnd,
      onPanResponderTerminationRequest: () => false,
      onPanResponderTerminate: this._handlePanResponderEnd,
    });
    this.state = {
      value: props.value || props.min,
    };
    this._containerRef = React.createRef();
  }
  _handlePanResponderGrant = () => {
    /*
     * 記錄開始滑動(dòng)開始時(shí)的滑塊值、弧度和坐標(biāo),用戶后續(xù)值的計(jì)算
     */
    const {value} = this.state;
    this._moveStartValue = value;
    // 獲取開始移動(dòng)的弧度
    this._moveStartRadian = this.getRadianByValue(value);
    // 根據(jù)弧度獲取開始的極坐標(biāo)
    this._startCartesian = this.polarToCartesian(this._moveStartRadian);
    // console.log(`開始滑動(dòng)弧度${this._startCartesian}`);
    // console.log(`開始滑動(dòng)${this._startCartesian.x}:${this._startCartesian.y}`);
  };
  _handlePanResponderMove = (e, gestureState) => {
    const {min, max, step, openingRadian} = this.props;
    let {x, y} = this._startCartesian;
    x += gestureState.dx;
    y += gestureState.dy;
    // console.log(`滑動(dòng)過程中${x}:${y}`);
    const radian = this.cartesianToPolar(x, y); // 當(dāng)前弧度
    console.log(`滑動(dòng)過程中的弧度${radian}`);
    const ratio =
      (this._moveStartRadian - radian) / ((Math.PI - openingRadian) * 2); // 弧度變化所占比例
    const diff = max - min; // 最大值和最小值的差
    let value;
    if (step) {
      value = this._moveStartValue + Math.round((ratio * diff) / step) * step;
    } else {
      value = this._moveStartValue + ratio * diff;
    }
    // 處理極值
    value = Math.max(min, Math.min(max, value));
    this.setState({
      value,
    });
    // this.setState(({value: curValue}) => {
    //   value = Math.abs(value - curValue) > diff / 4 ? curValue : value; // 避免直接從最小值變?yōu)樽畲笾?
    //   return {value: Math.round(value)};
    // });
    this._fireChangeEvent('onChange');
  };
  _handlePanResponderEnd = (e, gestureState) => {
    if (this.props.disabled) {
      return;
    }
    this._fireChangeEvent('onComplete');
  };
  _fireChangeEvent = event => {
    if (this.props[event]) {
      this.props[event](this.state.value);
    }
  };
  /**
   * 極坐標(biāo)轉(zhuǎn)笛卡爾坐標(biāo)
   * @param {number} radian - 弧度表示的極角
   */
  polarToCartesian(radian) {
    const {radius} = this.props;
    const distance = radius + this._getExtraSize() / 2; // 圓心距離坐標(biāo)軸的距離
    const x = distance + radius * Math.sin(radian);
    const y = distance + radius * Math.cos(radian);
    return {x, y};
  }
  /**
   * 笛卡爾坐標(biāo)轉(zhuǎn)極坐標(biāo)
   * @param {*} x
   * @param {*} y
   */
  cartesianToPolar(x, y) {
    const {radius} = this.props;
    const distance = radius + this._getExtraSize() / 2; // 圓心距離坐標(biāo)軸的距離
    if (x === distance) {
      return y > distance ? 0 : Math.PI / 2;
    }
    const a = Math.atan((y - distance) / (x - distance)); // 計(jì)算點(diǎn)與圓心連線和 x 軸的夾角
    return (x < distance ? (Math.PI * 3) / 2 : Math.PI / 2) - a;
  }
  /**
   * 獲取當(dāng)前弧度
   */
  getCurrentRadian() {
    return this.getRadianByValue(this.state.value);
  }
  /**
   * 根據(jù)滑塊的值獲取弧度
   * @param {*} value
   */
  getRadianByValue(value) {
    const {openingRadian, min, max} = this.props;
    return (
      ((Math.PI - openingRadian) * 2 * (max - value)) / (max - min) +
      openingRadian
    );
  }
  /**
   * 獲取除半徑外額外的大小,返回線寬和按鈕直徑中較大的
   */
  _getExtraSize() {
    const {strokeWidth, buttonRadius, buttonStrokeWidth} = this.props;
    return Math.max(strokeWidth, (buttonRadius + buttonStrokeWidth) * 2);
  }
  _onLayout = () => {
    const ref = this._containerRef.current;
    if (ref) {
      ref.measure((x, y, width, height, pageX, pageY) => {
        this.vertexX = pageX;
        this.vertexY = pageY;
      });
    }
  };
  render() {
    const {
      radius,
      strokeWidth,
      backgroundTrackColor,
      openingRadian,
      linearGradient,
      buttonRadius,
      buttonBorderColor,
      buttonFillColor,
      buttonStrokeWidth,
      style,
      contentContainerStyle,
      children,
    } = this.props;
    const svgSize = radius * 2 + this._getExtraSize();
    const startRadian = 2 * Math.PI - openingRadian; // 起點(diǎn)弧度
    const startPoint = this.polarToCartesian(startRadian);
    const endPoint = this.polarToCartesian(openingRadian);
    const currentRadian = this.getCurrentRadian(); // 當(dāng)前弧度
    const curPoint = this.polarToCartesian(currentRadian);
    const contentStyle = [styles.content, contentContainerStyle];
    return (
      <View
        onLayout={this._onLayout}
        ref={this._containerRef}
        style={[styles.container, style]}>
        <Svg width={svgSize} height={svgSize}>
          <Defs>
            <LinearGradient x1="0%" y1="100%" x2="100%" y2="0%" id="gradient">
              {linearGradient.map((item, index) => (
                <Stop key={index} offset={item.stop} stopColor={item.color} />
              ))}
            </LinearGradient>
          </Defs>
          <G rotation={0} origin={`${svgSize / 2}, ${svgSize / 2}`}>
            <Path
              strokeWidth={strokeWidth}
              stroke={backgroundTrackColor}
              fill="none"
              strokeLinecap="round"
              d={`M${startPoint.x},${startPoint.y} A ${radius},${radius},0,${
                startRadian - openingRadian >= Math.PI ? '1' : '0'
              },1,${endPoint.x},${endPoint.y}`}
            />
            <Path
              strokeWidth={strokeWidth}
              stroke="url(#gradient)"
              fill="none"
              strokeLinecap="round"
              d={`M${startPoint.x},${startPoint.y} A ${radius},${radius},0,${
                startRadian - currentRadian >= Math.PI ? '1' : '0'
              },1,${curPoint.x},${curPoint.y}`}
            />
            <Circle
              cx={curPoint.x}
              cy={curPoint.y}
              r={buttonRadius}
              fill={buttonFillColor || buttonBorderColor}
              stroke={buttonBorderColor}
              strokeWidth={buttonStrokeWidth}
              {...this._panResponder.panHandlers}
            />
          </G>
        </Svg>
        <View style={contentStyle} pointerEvents="box-none">
          {children}
        </View>
      </View>
    );
  }
}
const styles = StyleSheet.create({
  container: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  content: {
    position: 'absolute',
    left: 0,
    top: 0,
    bottom: 0,
    right: 0,
  },
});

到此這篇關(guān)于ReactNative實(shí)現(xiàn)弧形拖動(dòng)條的文章就介紹到這了,更多相關(guān)ReactNative弧形拖動(dòng)條內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解React 和 Redux的關(guān)系

    詳解React 和 Redux的關(guān)系

    這篇文章主要為大家介紹了React 和 Redux的關(guān)系,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • react項(xiàng)目引入scss的方法

    react項(xiàng)目引入scss的方法

    這篇文章主要介紹了react項(xiàng)目引入scss的方法,本文給大家介紹了React pwa的配置方法,通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • react-intl實(shí)現(xiàn)React國(guó)際化多語言的方法

    react-intl實(shí)現(xiàn)React國(guó)際化多語言的方法

    這篇文章主要介紹了react-intl實(shí)現(xiàn)React國(guó)際化多語言的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • react如何使用mobx6動(dòng)態(tài)加載數(shù)據(jù)

    react如何使用mobx6動(dòng)態(tài)加載數(shù)據(jù)

    MobX是一個(gè)強(qiáng)大而簡(jiǎn)單的狀態(tài)管理工具,它可以幫助我們更好地組織和管理React應(yīng)用程序中的數(shù)據(jù)流,本文給大家介紹react如何使用mobx6動(dòng)態(tài)加載數(shù)據(jù),感興趣的朋友跟隨小編一起看看吧
    2024-02-02
  • React?中在?map()?中使用條件跳出map的方法

    React?中在?map()?中使用條件跳出map的方法

    這篇文章主要介紹了React?中在?map()?中使用條件跳出map的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-09-09
  • React、Vue中key的作用詳解 (key的內(nèi)部原理解析)

    React、Vue中key的作用詳解 (key的內(nèi)部原理解析)

    key是虛擬DOM對(duì)象的標(biāo)識(shí),當(dāng)狀態(tài)中的數(shù)據(jù)發(fā)生變化時(shí),Vue會(huì)根據(jù)[新數(shù)據(jù)]生成[新的虛擬DOM],本文給大家介紹React、Vue中key的作用詳解 (key的內(nèi)部原理解析),感興趣的朋友一起看看吧
    2023-10-10
  • react事件對(duì)象無法獲取offsetLeft,offsetTop,X,Y等元素問題及解決

    react事件對(duì)象無法獲取offsetLeft,offsetTop,X,Y等元素問題及解決

    這篇文章主要介紹了react事件對(duì)象無法獲取offsetLeft,offsetTop,X,Y等元素問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。
    2022-08-08
  • 如何在React項(xiàng)目中引入字體文件并使用詳解

    如何在React項(xiàng)目中引入字體文件并使用詳解

    我們項(xiàng)目中通常會(huì)需要引入字體,所以下面這篇文章主要給大家介紹了關(guān)于如何在React項(xiàng)目中引入字體文件并使用的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • React Fiber源碼深入分析

    React Fiber源碼深入分析

    Fiber 可以理解為一個(gè)執(zhí)行單元,每次執(zhí)行完一個(gè)執(zhí)行單元,React Fiber就會(huì)檢查還剩多少時(shí)間,如果沒有時(shí)間則將控制權(quán)讓出去,然后由瀏覽器執(zhí)行渲染操作,這篇文章主要介紹了React Fiber架構(gòu)原理剖析,需要的朋友可以參考下
    2022-11-11
  • antd4里table滾動(dòng)的實(shí)現(xiàn)

    antd4里table滾動(dòng)的實(shí)現(xiàn)

    本文主要介紹了antd4里table滾動(dòng)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03

最新評(píng)論