ReactNative实现弧形拖动条

我们直接看效果

先看下面的使用代码

     <CircularSlider5step={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, // 开口弧度,为了便于计算值为实际开口弧度的一半

    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, // 开口弧度,为了便于计算值为实际开口弧度的一半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 = () => {/** 记录开始滑动开始时的滑块值、弧度和坐标,用户后续值的计算*/const {value} = this.state;this._moveStartValue = value;// 获取开始移动的弧度this._moveStartRadian = this.getRadianByValue(value);// 根据弧度获取开始的极坐标this._startCartesian = this.polarToCartesian(this._moveStartRadian);// console.log(`开始滑动弧度${this._startCartesian}`);// console.log(`开始滑动${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(`滑动过程中${x}:${y}`);const radian = this.cartesianToPolar(x, y); // 当前弧度console.log(`滑动过程中的弧度${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; // 避免直接从最小值变为最大值//   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);}};/*** 极坐标转笛卡尔坐标* @param {number} radian - 弧度表示的极角*/polarToCartesian(radian) {const {radius} = this.props;const distance = radius + this._getExtraSize() / 2; // 圆心距离坐标轴的距离const x = distance + radius * Math.sin(radian);const y = distance + radius * Math.cos(radian);return {x, y};}/*** 笛卡尔坐标转极坐标* @param {*} x* @param {*} y*/cartesianToPolar(x, y) {const {radius} = this.props;const distance = radius + this._getExtraSize() / 2; // 圆心距离坐标轴的距离if (x === distance) {return y > distance ? 0 : Math.PI / 2;}const a = Math.atan((y - distance) / (x - distance)); // 计算点与圆心连线和 x 轴的夹角return (x < distance ? (Math.PI * 3) / 2 : Math.PI / 2) - a;}/*** 获取当前弧度*/getCurrentRadian() {return this.getRadianByValue(this.state.value);}/*** 根据滑块的值获取弧度* @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; // 起点弧度const startPoint = this.polarToCartesian(startRadian);const endPoint = this.polarToCartesian(openingRadian);const currentRadian = this.getCurrentRadian(); // 当前弧度const curPoint = this.polarToCartesian(currentRadian);const contentStyle = [styles.content, contentContainerStyle];return (<ViewonLayout={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}`}><PathstrokeWidth={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}`}/><PathstrokeWidth={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}`}/><Circlecx={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,},
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/668034.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

centos7安装google chrome和chromium

一、下载安装包 wget https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm创建一个文件夹&#xff0c;把安装包放到文件夹内 mkdir ./google_chrome mv google-chrome-stable_current_x86_64.rpm ./google_chrome/ 二、安装 注意千万不要使用 rpm…

FreeCAD的python脚本编写

简介 FreeCAD是一款强大的开源CAD软件&#xff0c;可以与python无缝对解&#xff0c;使用python来驱动三维几何的构建&#xff0c;具有很高的灵活性。本文主要讨论一下录制宏的方法&#xff0c;以及如何驱动特定参数 方法 打开FreeCAD软件&#xff0c;点击录制宏按钮后&…

建筑行业数字化:从设计到运维的全面革新

随着科技的快速发展&#xff0c;数字化技术在各行各业中的应用越来越广泛。建筑行业作为传统产业&#xff0c;也在积极拥抱数字化技术&#xff0c;以提高效率、降低成本并实现可持续发展。本文将主要探讨建筑行业数字化的几个关键领域&#xff0c;包括建筑设计数字化、施工管理…

配置visualsvn提交后自动邮件通知

参考&#xff1a; https://blog.csdn.net/wiker_yong/article/details/10334967 # -*- coding: utf-8 -*- import sys import os import smtplib from email.mime.text import MIMEText from email.header import Headermail_host smtp.163.com #发送邮件的smtp地址 mail_us…

JS第二天、原型、原型链、正则

☆☆☆☆ 什么是原型&#xff1f; 构造函数的prototype 就是原型 专门保存所有子对象共有属性和方法的对象一个对象的原型就是它的构造函数的prototype属性的值。prototype是哪来的&#xff1f;所有的函数都有一个prototype属性当函数被创建的时候&#xff0c;prototype属性…

记录分享Spring Boot集成MQTT(配有简单实现示例)

Spring Boot集成MQTT是一个相对复杂的过程&#xff0c;需要涉及到多个步骤和配置。以下是一个详细的集成文档&#xff0c;包括操作步骤和简单的示例。 一、背景介绍 MQTT是一种轻量级的发布/订阅消息传输协议&#xff0c;广泛应用于物联网领域。Spring Boot是一个快速构建Spr…

vscode的vetur文档格式化失效

如果vscode安装了vetur插件之后&#xff0c;shiftAltF又无法格式化vue文件代码。 解决办法&#xff1a;打开文件 ---> 首选项 ---> 设置&#xff0c;搜索 vetur.format.defaultFormatter.html后将prettier替换勾选为js-beautify-html 注&#xff1a;设置下划线了并可以在…

常见Web前端开发框架推荐

在当今的Web开发领域&#xff0c;前端开发框架扮演着越来越重要的角色。它们不仅简化了开发过程&#xff0c;提高了开发效率&#xff0c;而且为开发者提供了丰富的特性和工具&#xff0c;使得创建复杂、高效的Web应用成为可能。以下是一些常见的Web前端开发框架&#xff0c;以及…

Lightroom Classic 2024 --- LR2024

Lightroom Classic 2024是一款专业的图片编辑和照片管理软件&#xff0c;旨在帮助摄影师高效地处理、编辑和展示他们的作品。通过强大的组织工具&#xff0c;用户可以轻松地管理、搜索和筛选大量的照片。该软件提供了全面的编辑工具&#xff0c;包括调整颜色、曝光、对比度、白…

Linux网络通信——TCP/OSI七层模型/TCP/IP(五层或四层模型)/HTTP报文传输原理

文章目录 消息的传输什么是OSI七层模型OSI七层模型的内容物理层&#xff08;Physical Layer&#xff09;&#xff1a;数据链路层&#xff08;Data Link Layer&#xff09;&#xff1a;网络层&#xff08;Network Layer&#xff09;&#xff1a;传输层&#xff08;Transport Lay…

On the Spectral Bias of Neural Networks论文阅读

1. 摘要 众所周知&#xff0c;过度参数化的深度神经网络(DNNs)是一种表达能力极强的函数&#xff0c;它甚至可以以100%的训练精度记忆随机数据。这就提出了一个问题&#xff0c;为什么他们不能轻易地对真实数据进行拟合呢。为了回答这个问题&#xff0c;研究人员使用傅里叶分析…

Oracle12c之Sqlplus命令行窗口基本使用

Oracle12c之Sqlplus命令行窗口基本使用 文章目录 Oracle12c之Sqlplus命令行窗口基本使用1. 连接1. 超级用户2. 普通用户1. 创建普通用2. 连接 2. 修改用户连接数1. 查看默认连接最多用户数1. PL/SQL developer中查看2. Sqlplus中查看 2. 查看目前已经连接的用户数3. 修改用户连…

ThinkPHP6进阶教程:如何优雅地使用Auth模块进行权限验证

thinkphp6是一款优秀的php框架&#xff0c;它为我们提供了很多高效的工具和功能。其中&#xff0c;auth授权是一个非常强大的功能&#xff0c;可以帮助我们在应用程序中进行权限管理。本文将介绍如何使用thinkphp6的auth授权。 安装Auth组件 首先&#xff0c;我们需要安装Aut…

设计模式-行为型模式(上)

行为型模式用于描述程序在运行时复杂的流程控制&#xff0c;即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务&#xff0c;它涉及算法与对象间职责的分配。 行为型模式分为类行为模式和对象行为模式&#xff0c;前者采用继承机制来在类间分派行为&…

Docker 搭建mysql 集群(二)

PXC方案 很明显 PXC方案在任何一个节点写入的数据都会同步到其他节点&#xff0c;数据双向同步的&#xff08;在任何节点上都可以同时读写&#xff09; 创建MySQL PXC集群 1 安装PXC镜像 docker pull percona/percona-xtradb-cluster:5.7.21 2 为PXC镜像改名 docker tag pe…

如何选择旅游路线,使得假期旅游路费最少?

旅行是许多人的热爱&#xff0c;但是在规划一个完美的假期时&#xff0c;找到最经济的路线常常是一个挑战。这里就需要引入一个著名的优化问题——旅行商问题。本文将介绍TSP的基础知识&#xff0c;并使用MTZ消除子环方法优化一个简单的TSP问题的示例。 旅行商问题简介 TSP&a…

用友U8 Cloud ReportDetailDataQuery SQL注入漏洞复现(QVD-2023-47860)

0x01 产品简介 用友U8 Cloud 提供企业级云ERP整体解决方案,全面支持多组织业务协同,实现企业互联网资源连接。 U8 Cloud 亦是亚太地区成长型企业最广泛采用的云解决方案。 0x02 漏洞概述 用友U8 cloud ReportDetailDataQuery 接口处存在SQL注入漏洞,攻击者未经授权可以访…

自然语言nlp学习五

6-10 文本生成--介绍_哔哩哔哩_bilibili 在自然语言处理&#xff08;NLP, Natural Language Processing&#xff09;领域&#xff0c;“sequence”通常是指一个有序的数据集合&#xff0c;它由一系列元素按照特定顺序排列而成。这些元素可以是单词、字符、句子或其他文本单位。…

NLP_语言模型的雏形N-Gram

文章目录 N-Gram 模型1.将给定的文本分割成连续的N个词的组合(N-Gram)2.统计每个N-Gram在文本中出现的次数&#xff0c;也就是词频3.为了得到一个词在给定上下文中出现的概率&#xff0c;我们可以利用条件概率公式计算。具体来讲&#xff0c;就是计算给定前N-1个词时&#xff0…

Adobe Illustrator CEP插件开发入门指南

引言 Adobe Creative Cloud&#xff08;创意云&#xff09;中的Illustrator作为一款全球领先的矢量图形设计软件&#xff0c;为设计师提供了丰富的功能和无限的创作可能性。为了进一步增强其功能并满足个性化工作流程需求&#xff0c;Adobe引入了Common Extensibility Platform…