900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 微信小程序自定义封装环形进度条组件

微信小程序自定义封装环形进度条组件

时间:2024-02-16 00:30:15

相关推荐

微信小程序自定义封装环形进度条组件

我们先看效果-选不了视频没办法了

说明:此组件对圆的宽度,进度条的宽度、颜色、旋转方向,还有进度条的值,还有两端是否要圆角都进行了动态化,无坑可放心用,参数解释在注释里,我就不写了。效果图看到尾部的小圆点位置不太对,但是在真机模式下看就是正常的

一、子组件-先写html

<view class="progress"><view class="circle" style="width:{{progressBar.size}};height:{{progressBar.size}};background: conic-gradient({{progressBar.progressColor}} 0, {{progress}}%, {{progressBar.progressBackgroundColor}} 0%);transform:rotateY({{progressBar.direction == 'cw' ? '0deg' : '180deg'}});"><view class="start-dot" wx:if="{{progressBar.num>0}}" style="width:{{dotSize}};height:{{dotSize}};background-color: {{progressBar.progressColor}};opacity: {{progressBar.endDot&&progressBar.startDot&&progressBar.num>0?1:0}};"></view><view class="background" style="background-color: {{progressBar.backgroundColor}}; width:{{backgroundSize}}; height:{{backgroundSize}}"><view class="end-dot" style="background-color: {{progressBar.progressColor}};width:{{dotSize}};height:{{dotSize}};opacity: {{progressBar.endDotShow&&progressBar.endDot&&progressBar.num>0?1:0}} ;transform-origin: calc(100% + {{dotOrigin}});transform: translateX(-100%) translateY(-50%) rotate({{dotEeg}}deg);"></view></view></view><text wx:if="{{progressText.show}}" style="{{ progressText.style }}" class="text">{{ progressText.text }}%</text></view>

二、子组件-js--这是我朋友写的,很多地方我不理解就加了注释,提供一下transform-origin的学习和圆运动的参考链接

1.CSS3之transform-origin详解_爪蛙没有爪的博客-CSDN博客_transform-origin

2.缓动函数(easing function)

3.动画运动 缓动算法(easing function) - 掘金

let timer = null;Component({/*** 组件的属性列表*/properties: {progressBar: {type: Object,value: {num: 0, //当前进度 0~100direction: 'cw', //方向, cw顺时针, cww逆时针size: "400rpx", //大小duration: 450, //动画持续时间progressColor: 'rgb(41,132,237)', //进度条的颜色progressBackgroundColor: '#eaeaea', //进度条占位颜色backgroundColor: '#ffffff', //中间的背景色progressWidth: '30rpx', //进度条宽度startDot: true,//进度条开始圆点endDot: true,//进度条结束圆点endDotShow: false,}},},/*** 组件的初始数据*/data: {progress: 0,progressText: {text: 0,style: '',show: true,},progressColor: 'red',backgroundSize: '180rpx',dotSize: '10rpx',dotEeg: 90,dotOrigin: '90rpx',},attached() {},observers: {// 大圆的宽,返回小点的大小,绕着多大转'progressBar.size': function (val) {const _this = this;let unit = val.replace(/[0-9]/ig, "");let size = parseFloat(val); // parseFloat 只要数字let backgroundSize = size - parseFloat(this.data.progressBar.progressWidth);// 传来的 圆的外层400rpx,进度条宽度30rpx// console.log(backgroundSize,69);//370// createSelectorQuery 获取页面中界面上的节点信息的是在Page中获取的// 返回一个SelectorQuery 对象实例。在自定义组件或包含自定义组件的页面中,应使用this.createSelectorQuery()来代替let query = this.createSelectorQuery();// boundingClientRect 用来确定某个元素query.select('.background').boundingClientRect(function (rect) {// console.log(rect.width,8887);_this.setData({backgroundSize: `${backgroundSize}${unit}`,dotOrigin: `${rect.width / 2}px`// rect.width= 185,是370的一半,370=大宽-进度条宽度,验证了确实这样});}).exec();},// 进度条宽度=传进来大宽的宽度-传进来进度条的宽度'progressBar.progressWidth': function (val) {let unit = val.replace(/[0-9]/ig, "");let size = parseFloat(this.data.progressBar.size);val = parseFloat(val);let backgroundSize = size - val;this.setData({backgroundSize: `${backgroundSize}${unit}`,});let query = this.createSelectorQuery();query.select('.circle').boundingClientRect();query.select('.background').boundingClientRect();query.exec(res => {// res[0].width=200,是传进来大宽的一半// res[1].width=185,是370的一半,370=大宽-进度条宽度,验证了没问题let dotSize = (res[0].width - res[1].width) / 2;// 这里是算那两个小点点的大小this.setData({dotSize: `${dotSize}px`});});},//当前进度,由父组件传来,现在是50'progressBar.num': function (val) {// console.log(val,'103val');if (timer) {clearTimeout(timer);}val = Math.round(val * 100) / 100;let begin = this.data.progress;// 当前时间,默认0let change = val - begin;// 起始位置// console.log(val,begin,111);// 50 - 0let time = 0;let duration = this.data.progressBar.duration / 1000;// 动画时长,父组件传来1000if (val > this.data.progress) {if (val >= 100) {this.setData({"progressText.text": 100,});}const step = () => {let value = this.easeInOut(time, begin, change, duration);// console.log(value,131);// 从0到49.96000001,用于渐变色中间是怎么样的// console.log(time, begin, change, duration,'127');// time每次加0.02,直到1,可能是因为我传进来的是1000ms,确实,144行限制了小于duration,就是1秒// begin:当前时间,默认0,没有被改变// change:起始位置 50,就是传来的进度50// duration:动画时长,计算得出1// let value = this.linear(time, begin, change, duration);// console.log(time, begin, change, duration,'126');// progress 用于渐变色中间是怎么样的// progressText.text 就是进度,四舍五入this.setData({progress: value,'progressText.text': Math.round(value),dotEeg: 90 + this.getDotDeg(value)});// console.log(this.data.dotEeg,this.getDotDeg(value),147); // 这个90度要加,因为一开始的位置是在左边的中间的,要加90才能回来上面的顶部,才可以正常滚动对的角度// this.getDotDeg(value),value从0-接近50不停变化,给函数计算,time += 0.02;if (time <= duration) {this.startAnimation(step);return;}if (val >= 100) {this.setData({progress: 101,'progressText.text': 100,dotEeg: 90 + this.getDotDeg(100)});return;}this.setData({progress: val,'progressText.text': val,dotEeg: 90 + this.getDotDeg(val)});};// step定义了, 得有一次执行, 不执行里面的东西不能运行step();return;}this.setData({progress: val,"progressText.text": val,});},},lifetimes: {attached() {this.setData({// 'progressBar.size': this.properties.progressBar.size});},ready() {setTimeout(() => {this.setData({'progressBar.endDotShow': true})}, 100);}},/*** 组件的方法列表*/methods: {startAnimation(fn) {timer = setTimeout(fn, 17)},linear(time, begin, change, duration) {// console.log(time, begin, change, duration,'193');return change * time / duration + begin;},easeInOut(time, begin, change, duration) {if ((time /= duration / 2) < 1) return change / 2 * time * time + begin;// console.log(-change / 2 * ((--time) * (time - 2) - 1) + begin,8888);//从0.02到49.96000001return -change / 2 * ((--time) * (time - 2) - 1) + begin;},getDotDeg(val) {// console.log(val,208);// 比如传入50,val这个值就是从0-50return 360 * val / 100;}}});

四、子组件-css

.progress {position: relative;display: flex;justify-content: center;align-items: center;}.circle {border-radius: 50%;position: relative;display: flex;justify-content: center;align-items: center;/* transform: rotateY(180deg); */}.start-dot {position: absolute;top: 0;width: 25rpx;height: 25rpx;background-color: rgb(41,132,237);border-radius: 50%;}.end-dot {position: absolute;top: 50%;left: 0%;width: 25rpx;height: 25rpx;background-color: rgb(41,132,237);border-radius: 50%;}.background {background-color: #ffffff;border-radius: 50%;display: flex;justify-content: center;align-items: center;position: relative;}.text {position: absolute;}

五、父组件-html

<progressBar progressBar="{{progressBar}}" /><view class="btn"><button bindtap="sum">➕</button></view>

六、父组件-js--记得先引入组件哦,参数都有写注释~没有坑可放心用,不过可能我删了别的多余的代码不小心把"},"之类的删掉了,要自己检查一下哈哈

// index.js// 获取应用实例const app = getApp()Page({data: {progressBar:{num: 50, //当前进度 0~100direction: 'cw', //方向, cw顺时针, cww逆时针size: "400rpx", //大小duration: 1000, //动画持续时间progressColor: 'rgb(41,132,237)', //进度条的颜色progressBackgroundColor: '#eaeaea', //进度条占位颜色backgroundColor: '#ffffff', //中间的背景色progressWidth: '30rpx', //进度条宽度startDot:true,//进度条开始圆点endDot:true,//进度条结束圆点},sum() {let random = Math.random() * 9 + 1;if (this.data.progressBar.num + random >= 100) {this.setData({'progressBar.num': 100,});return;}this.setData({'progressBar.num': this.data.progressBar.num + random});},})

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。