怎么用react native实现圆弧拖动进度条
发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,这篇"怎么用react native实现圆弧拖动进度条"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们
千家信息网最后更新 2026年11月03日怎么用react native实现圆弧拖动进度条
这篇"怎么用react native实现圆弧拖动进度条"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇"怎么用react native实现圆弧拖动进度条"文章吧。
先上效果图
因为需求需要实现这个效果图 非原生实现,
难点1:绘制 使用svg
难点2:点击事件的处理
难点3:封装
由于绘制需要是使用svg
此处自行百度 按照svg以及api 教学
视图代码块
render() { return ( //实际圆环 {this._renderCircleSvg()} // 计算中心距离 // 暴露给外部渲染圆环中心的接口 {this.props.renderCenterView(this.state.temp)} ); _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 ( ); }}事件处理代码块
// 参考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 ( {this._renderCircleSvg()} {this.props.renderCenterView(this.state.temp)} ); } _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 ( ); }}const styles = StyleSheet.create({ svg: {},});外部调用
{ }} valueChange={temp => {}} renderCenterView={temp => ( )} enTouch={true} />
以上就是关于"怎么用react native实现圆弧拖动进度条"这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注行业资讯频道。
响应者
组件
进度
内容
手势
圆弧
处理
代码
就是
效果
象限
难点
参考
事件
事情
圆环
布尔
效果图
数学
文章
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
科技和互联网公司
工业互联网科技新基建
科技服务与互联网
美国互联网科技
互联网 科技创业
互联网 的科技创新
嘟嘟瓜互联网科技
极限挑战互联网科技
腾讯科技 互联网女皇
互联网科技有哪些公司
互联网科技项目计划书材料类
996高科技互联网公司
山东子淼互联网科技有限公司
每天都有哪些好的互联网科技
智帮互联网科技公司最近动向
富国互联网金融科技混合基金
珠海东科互联网科技有限公司
北京天晋互联网科技有限公司
亚光科技低轨卫星互联网
北京瑞云互联网科技有限公司
手冲咖啡和咖啡机区别
互联网黑科技
互联网科技的英文
米客互联网科技
深圳期待互联网科技
明优互联网科技有限公司
科技大学互联网
山东子淼互联网科技有限公司
卡尔迅互联网科技有限公司
六子台科技互联网展会