我的编程空间,编程开发者的网络收藏夹
学习永远不晚

怎么用react native实现圆弧拖动进度条

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

怎么用react native实现圆弧拖动进度条

这篇“怎么用react native实现圆弧拖动进度条”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么用react native实现圆弧拖动进度条”文章吧。

先上效果图

怎么用react native实现圆弧拖动进度条

因为需求需要实现这个效果图 非原生实现,

  1. 难点1:绘制 使用svg

  2. 难点2:点击事件的处理

  3. 难点3:封装

由于绘制需要是使用svg

此处自行百度 按照svg以及api 教学

视图代码块

 render() { return (  <View pointerEvents={'box-only'}  //事件处理  {...this._panResponder.panHandlers}>  //实际圆环  {this._renderCircleSvg()}  // 计算中心距离  <View   style={{   position: 'relative',   top: -this.props.height / 2 - this.props.r,   left: this.props.width / 2 - this.props.r,   flex: 1,   }}>   // 暴露给外部渲染圆环中心的接口   {this.props.renderCenterView(this.state.temp)}  </View>  </View> ); _renderCircleSvg() { //中心点 const cx = this.props.width / 2; const cy = this.props.height / 2; //计算是否有偏差角 对应图就是下面缺了一块的 const prad = this.props.angle / 2 * (Math.PI / 180); //三角计算起点 const startX = -(Math.sin(prad) * this.props.r) + cx; const startY = cy + Math.cos(prad) * this.props.r;  //终点 const endX = Math.sin(prad) * this.props.r + cx; const endY = cy + Math.cos(prad) * this.props.r; // 计算进度点 const progress = parseInt(  this._circlerate() * (360 - this.props.angle) / 100,  10 ); // 根据象限做处理 苦苦苦 高中数学全忘了,参考辅助线 const t = progress + this.props.angle / 2; const progressX = cx - Math.sin(t * (Math.PI / 180)) * this.props.r; const progressY = cy + Math.cos(t * (Math.PI / 180)) * this.props.r;// SVG的描述 这里百度下就知道什么意思 const descriptions = [  'M',  startX,  startY,  'A',  this.props.r,  this.props.r,  0,  1,  1,  endX,  endY, ].join(' '); const progressdescription = [  'M',  startX,  startY,  'A',  this.props.r,  this.props.r,  0,  //根据角度是否是0,1 看下效果就知道了  t >= 180 + this.props.angle / 2 ? 1 : 0,  1,  progressX,  progressY, ].join(' '); return (  <Svg  height={this.props.height}  width={this.props.width}  style={styles.svg}>  <Path   d={descriptions}   fill="none"   stroke={this.props.outArcColor}   strokeWidth={this.props.strokeWidth} />  <Path   d={progressdescription}   fill="none"   stroke={this.props.progressvalue}   strokeWidth={this.props.strokeWidth} />  <Circle   cx={progressX}   cy={progressY}   r={this.props.tabR}   stroke={this.props.tabStrokeColor}   strokeWidth={this.props.tabStrokeWidth}   fill={this.props.tabColor} />  </Svg> ); }}

事件处理代码块

// 参考react native 官网对手势的讲解 iniPanResponder() { this.parseToDeg = this.parseToDeg.bind(this); this._panResponder = PanResponder.create({  // 要求成为响应者:  onStartShouldSetPanResponder: () => true,  onStartShouldSetPanResponderCapture: () => true,  onMoveShouldSetPanResponder: () => true,  onMoveShouldSetPanResponderCapture: () => true,  onPanResponderGrant: evt => {  // 开始手势操作。给用户一些视觉反馈,让他们知道发生了什么事情!  if (this.props.enTouch) {   this.lastTemper = this.state.temp;   const x = evt.nativeEvent.locationX;   const y = evt.nativeEvent.locationY;   this.parseToDeg(x, y);  }  },  onPanResponderMove: (evt, gestureState) => {  if (this.props.enTouch) {   let x = evt.nativeEvent.locationX;   let y = evt.nativeEvent.locationY;   if (Platform.OS === 'android') {   x = evt.nativeEvent.locationX + gestureState.dx;   y = evt.nativeEvent.locationY + gestureState.dy;   }   this.parseToDeg(x, y);  }  },  onPanResponderTerminationRequest: () => true,  onPanResponderRelease: () => {  if (this.props.enTouch) this.props.complete(this.state.temp);  },  // 另一个组件已经成为了新的响应者,所以当前手势将被取消。  onPanResponderTerminate: () => {},  // 返回一个布尔值,决定当前组件是否应该阻止原生组件成为JS响应者  // 默认返回true。目前暂时只支持android。  onShouldBlockNativeResponder: () => true, }); }//画象限看看就知道了 就是和中线点计算角度parseToDeg(x, y) { const cx = this.props.width / 2; const cy = this.props.height / 2; let deg; let temp; if (x >= cx && y <= cy) {  deg = Math.atan((cy - y) / (x - cx)) * 180 / Math.PI;  temp =  (270 - deg - this.props.angle / 2) /   (360 - this.props.angle) *   (this.props.max - this.props.min) +  this.props.min; } else if (x >= cx && y >= cy) {  deg = Math.atan((cy - y) / (cx - x)) * 180 / Math.PI;  temp =  (270 + deg - this.props.angle / 2) /   (360 - this.props.angle) *   (this.props.max - this.props.min) +  this.props.min; } else if (x <= cx && y <= cy) {  deg = Math.atan((x - cx) / (y - cy)) * 180 / Math.PI;  temp =  (180 - this.props.angle / 2 - deg) /   (360 - this.props.angle) *   (this.props.max - this.props.min) +  this.props.min; } else if (x <= cx && y >= cy) {  deg = Math.atan((cx - x) / (y - cy)) * 180 / Math.PI;  if (deg < this.props.angle / 2) {  deg = this.props.angle / 2;  }  temp =  (deg - this.props.angle / 2) /   (360 - this.props.angle) *   (this.props.max - this.props.min) +  this.props.min; } if (temp <= this.props.min) {  temp = this.props.min; } if (temp >= this.props.max) {  temp = this.props.max; } //因为提供步长,所欲需要做接近步长的数 temp = this.getTemps(temp); this.setState({  temp, }); this.props.valueChange(this.state.temp); } getTemps(tmps) { const k = parseInt((tmps - this.props.min) / this.props.step, 10); const k1 = this.props.min + this.props.step * k; const k2 = this.props.min + this.props.step * (k + 1); if (Math.abs(k1 - tmps) > Math.abs(k2 - tmps)) return k2; return k1; }

完整代码块

import React, { Component } from 'react';import { View, StyleSheet, PanResponder, Platform, Text } from 'react-native';import Svg, { Circle, Path } from 'react-native-svg';export default class CircleView extends Component { static propTypes = { height: React.PropTypes.number, width: React.PropTypes.number, r: React.PropTypes.number, angle: React.PropTypes.number, outArcColor: React.PropTypes.object, progressvalue: React.PropTypes.object, tabColor: React.PropTypes.object, tabStrokeColor: React.PropTypes.object, strokeWidth: React.PropTypes.number, value: React.PropTypes.number, min: React.PropTypes.number, max: React.PropTypes.number, tabR: React.PropTypes.number, step: React.PropTypes.number, tabStrokeWidth: React.PropTypes.number, valueChange: React.PropTypes.func, renderCenterView: React.PropTypes.func, complete: React.PropTypes.func, enTouch: React.PropTypes.boolean, }; static defaultProps = { width: 300, height: 300, r: 100, angle: 60, outArcColor: 'white', strokeWidth: 10, value: 20, min: 10, max: 70, progressvalue: '#ED8D1B', tabR: 15, tabColor: '#EFE526', tabStrokeWidth: 5, tabStrokeColor: '#86BA38', valueChange: () => {}, complete: () => {}, renderCenterView: () => {}, step: 1, enTouch: true, }; constructor(props) { super(props); this.state = {  temp: this.props.value, }; this.iniPanResponder(); } iniPanResponder() { this.parseToDeg = this.parseToDeg.bind(this); this._panResponder = PanResponder.create({  // 要求成为响应者:  onStartShouldSetPanResponder: () => true,  onStartShouldSetPanResponderCapture: () => true,  onMoveShouldSetPanResponder: () => true,  onMoveShouldSetPanResponderCapture: () => true,  onPanResponderGrant: evt => {  // 开始手势操作。给用户一些视觉反馈,让他们知道发生了什么事情!  if (this.props.enTouch) {   this.lastTemper = this.state.temp;   const x = evt.nativeEvent.locationX;   const y = evt.nativeEvent.locationY;   this.parseToDeg(x, y);  }  },  onPanResponderMove: (evt, gestureState) => {  if (this.props.enTouch) {   let x = evt.nativeEvent.locationX;   let y = evt.nativeEvent.locationY;   if (Platform.OS === 'android') {   x = evt.nativeEvent.locationX + gestureState.dx;   y = evt.nativeEvent.locationY + gestureState.dy;   }   this.parseToDeg(x, y);  }  },  onPanResponderTerminationRequest: () => true,  onPanResponderRelease: () => {  if (this.props.enTouch) this.props.complete(this.state.temp);  },  // 另一个组件已经成为了新的响应者,所以当前手势将被取消。  onPanResponderTerminate: () => {},  // 返回一个布尔值,决定当前组件是否应该阻止原生组件成为JS响应者  // 默认返回true。目前暂时只支持android。  onShouldBlockNativeResponder: () => true, }); } componentWillReceiveProps(nextProps) { if (nextProps.value != this.state.temp) {  this.state = {  temp: nextProps.value,  }; } } parseToDeg(x, y) { const cx = this.props.width / 2; const cy = this.props.height / 2; let deg; let temp; if (x >= cx && y <= cy) {  deg = Math.atan((cy - y) / (x - cx)) * 180 / Math.PI;  temp =  (270 - deg - this.props.angle / 2) /   (360 - this.props.angle) *   (this.props.max - this.props.min) +  this.props.min; } else if (x >= cx && y >= cy) {  deg = Math.atan((cy - y) / (cx - x)) * 180 / Math.PI;  temp =  (270 + deg - this.props.angle / 2) /   (360 - this.props.angle) *   (this.props.max - this.props.min) +  this.props.min; } else if (x <= cx && y <= cy) {  deg = Math.atan((x - cx) / (y - cy)) * 180 / Math.PI;  temp =  (180 - this.props.angle / 2 - deg) /   (360 - this.props.angle) *   (this.props.max - this.props.min) +  this.props.min; } else if (x <= cx && y >= cy) {  deg = Math.atan((cx - x) / (y - cy)) * 180 / Math.PI;  if (deg < this.props.angle / 2) {  deg = this.props.angle / 2;  }  temp =  (deg - this.props.angle / 2) /   (360 - this.props.angle) *   (this.props.max - this.props.min) +  this.props.min; } if (temp <= this.props.min) {  temp = this.props.min; } if (temp >= this.props.max) {  temp = this.props.max; } temp = this.getTemps(temp); this.setState({  temp, }); this.props.valueChange(this.state.temp); } getTemps(tmps) { const k = parseInt((tmps - this.props.min) / this.props.step, 10); const k1 = this.props.min + this.props.step * k; const k2 = this.props.min + this.props.step * (k + 1); if (Math.abs(k1 - tmps) > Math.abs(k2 - tmps)) return k2; return k1; } render() { return (  <View pointerEvents={'box-only'} {...this._panResponder.panHandlers}>  {this._renderCircleSvg()}  <View   style={{   position: 'relative',   top: -this.props.height / 2 - this.props.r,   left: this.props.width / 2 - this.props.r,   flex: 1,   }}>   {this.props.renderCenterView(this.state.temp)}  </View>  </View> ); } _circlerate() { let rate = parseInt(  (this.state.temp - this.props.min) *  100 /  (this.props.max - this.props.min),  10 ); if (rate < 0) {  rate = 0; } else if (rate > 100) {  rate = 100; } return rate; } _renderCircleSvg() { const cx = this.props.width / 2; const cy = this.props.height / 2; const prad = this.props.angle / 2 * (Math.PI / 180); const startX = -(Math.sin(prad) * this.props.r) + cx; const startY = cy + Math.cos(prad) * this.props.r; // // 最外层的圆弧配置 const endX = Math.sin(prad) * this.props.r + cx; const endY = cy + Math.cos(prad) * this.props.r; // 计算进度点 const progress = parseInt(  this._circlerate() * (360 - this.props.angle) / 100,  10 ); // 根据象限做处理 苦苦苦 高中数学全忘了,参考辅助线 const t = progress + this.props.angle / 2; const progressX = cx - Math.sin(t * (Math.PI / 180)) * this.props.r; const progressY = cy + Math.cos(t * (Math.PI / 180)) * this.props.r; const descriptions = [  'M',  startX,  startY,  'A',  this.props.r,  this.props.r,  0,  1,  1,  endX,  endY, ].join(' '); const progressdescription = [  'M',  startX,  startY,  'A',  this.props.r,  this.props.r,  0,  t >= 180 + this.props.angle / 2 ? 1 : 0,  1,  progressX,  progressY, ].join(' '); return (  <Svg  height={this.props.height}  width={this.props.width}  style={styles.svg}>  <Path   d={descriptions}   fill="none"   stroke={this.props.outArcColor}   strokeWidth={this.props.strokeWidth} />  <Path   d={progressdescription}   fill="none"   stroke={this.props.progressvalue}   strokeWidth={this.props.strokeWidth} />  <Circle   cx={progressX}   cy={progressY}   r={this.props.tabR}   stroke={this.props.tabStrokeColor}   strokeWidth={this.props.tabStrokeWidth}   fill={this.props.tabColor} />  </Svg> ); }}const styles = StyleSheet.create({ svg: {},});

外部调用

<View style={styles.container}>  <CircleProgress   width={width}   height={height}   r={r}   angle={60}   min={5}   max={35}   step={0.5}   value={22}   complete={temp => {   }}   valueChange={temp => {}}   renderCenterView={temp => (   <View style={{ flex: 1 }}>   </View>   )}   enTouch={true} />  </View>

以上就是关于“怎么用react native实现圆弧拖动进度条”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

怎么用react native实现圆弧拖动进度条

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

怎么用react native实现圆弧拖动进度条

这篇“怎么用react native实现圆弧拖动进度条”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么用react nat
2023-06-05

react可拖拽进度条怎么实现

本文小编为大家详细介绍“react可拖拽进度条怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“react可拖拽进度条怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。效果/* * @Author: h
2023-06-30

如何实现 Java 圆形进度条?(java圆形进度条怎么实现)

在Java开发中,实现圆形进度条是一个常见的需求,它可以为用户提供直观的操作反馈或展示任务的进度。以下是实现Java圆形进度条的详细步骤:一、准备工作开发环境搭建:确保你已经安装了Java开发环境,包括
如何实现 Java 圆形进度条?(java圆形进度条怎么实现)

Android怎么自定义View实现圆弧进度效果

这篇文章主要介绍“Android怎么自定义View实现圆弧进度效果”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Android怎么自定义View实现圆弧进度效果”文章能帮助大家解决问题。技术实现1.
2023-07-06

android圆形进度条怎么实现

要实现一个圆形进度条,你可以使用`ProgressBar`控件来实现,并将其样式设置为圆形。首先,在布局文件中添加以下代码:```xmlandroid:id="@+id/progressBar"style="?android:attr/pr
2023-08-30

java圆形进度条怎么实现

以下是一个简单的Java圆形进度条的实现代码:import java.awt.Color;import java.awt.Dimension;import java.awt.Graphics;import java.awt.Graphics
2023-05-13

MFC圆形进度条怎么实现

MFC(Microsoft Foundation Class)是用于开发Windows应用程序的一套类库。要实现MFC圆形进度条,可以按照以下步骤进行:1. 创建一个MFC项目,包括一个对话框窗口。2. 在对话框资源上添加一个静态文本框和一
2023-08-20

怎么用Android View实现圆形进度条

本篇内容主要讲解“怎么用Android View实现圆形进度条”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用Android View实现圆形进度条”吧!主要涉及到下面几个方法:// 画圆c
2023-06-20

使用canvas怎么实现一个圆形进度条动画

这期内容当中小编将会给大家带来有关使用canvas怎么实现一个圆形进度条动画,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1. canvas的HTML部分很简单就一个canvas标签canvas画布的宽高
2023-06-09

使用 css3怎么实现一个圆形进度条

使用 css3怎么实现一个圆形进度条?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。html代码
2023-06-08

怎么使用react native reanimated实现动画

这篇“怎么使用react native reanimated实现动画”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么使用r
2023-07-05

css怎么实现圆形渐变进度条效果

这篇文章给大家分享的是有关css怎么实现圆形渐变进度条效果的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。实现思路最外面是一个大圆(渐变色)内部里面绘制两个半圆,将渐变的圆遮住(为了看起来明显,左右两侧颜色不一样,
2023-06-08

微信小程序怎么实现圆心进度条

这篇文章主要介绍“微信小程序怎么实现圆心进度条”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“微信小程序怎么实现圆心进度条”文章能帮助大家解决问题。一、创建项目结构打开微信开发者工具创建一个项目, 新
2023-07-02

Android studio中怎么实现一个圆形进度条

Android studio中怎么实现一个圆形进度条,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。MainActivityimport android.support.v7.a
2023-05-30

Android怎么自定义View实现圆形进度条

本文小编为大家详细介绍“Android怎么自定义View实现圆形进度条”,内容详细,步骤清晰,细节处理妥当,希望这篇“Android怎么自定义View实现圆形进度条”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。原
2023-07-02

怎么在css3中使用clip实现一个圆环进度条

这期内容当中小编将会给大家带来有关怎么在css3中使用clip实现一个圆环进度条,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。实现思路圆环很简单,一行cssborder-radius:50%即可实现,而且
2023-06-08

vue中怎么使用SVG实现圆形进度条音乐播放

今天小编给大家分享一下vue中怎么使用SVG实现圆形进度条音乐播放的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。效果图:实现
2023-06-29

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录