[Uni-app] 微信小程序的圆环进度条

news2024/11/29 22:51:39

效果图:

组件完整代码如下:

<template>
  <view class="base-style"
    :style="'position: relative;width: ' + diameter + 'px;height: ' + diameter + 'px;display: flex;flex-direction: row;background-color: ' + bgColor + ';'">
    <!-- 左半圆和右半圆都要经历下面的5步:
    [第1步]第1层限定区域; 
    [第2步]第2层决定显示一个整圆的左半边还是右半边; 
    [第3步]第3层先使用激活颜色绘制一个圆环, 再添加一个同级且宽度为区域一半的盒子A;
    [第4步]在盒子A中再使用圆环底色绘制一个圆环, 此时整个圆环是 '左一半是激活颜色、右一半是圆环底色', 但这个圆环同时只能被看到一半;
    [第5步]旋转第2层。 -->

    <!-- 左半圆 -->
    <view class="base-style" :style="firstLayerViewStyle">
      <view :style="secondLayerViewStyle + secondLayerForLeft">
        <!-- 使用激活颜色绘制一个圆环。 -->
        <view :style="thirdLayerStyle">
        </view>
        <!-- 再使用背景色遮盖同级圆环的一半。 -->
        <view class="base-style" :style="thirdLayerStyleForBg">
          <view :style="fourthLayerStyleForBg" />
        </view>
        <view v-if="0 < ePercent && ePercent < 0.5" :style="endPointStyle + endPointStyleForLeft" />
      </view>
    </view>

    <!-- 右半圆 -->
    <view class="base-style" :style="firstLayerViewStyle">
      <!-- 适配:为了避免右侧遮盖显示不全 此处向左多移动了1px -->
      <view :style="secondLayerViewStyle + 'left: ' + (- diameter / 2 - 1) + 'px;' + secondLayerForRight">
        <!-- 使用激活颜色绘制一个圆环。 -->
        <view :style="thirdLayerStyle">
        </view>
        <!-- 再使用背景色遮盖同级圆环的一半。 -->
        <view class="base-style" :style="thirdLayerStyleForBg">
          <view :style="fourthLayerStyleForBg" />
        </view>
        <view v-if="ePercent > 0.5" :style="endPointStyle + endPointStyleForRight" />
      </view>
    </view>

    <view v-if="0.5 == ePercent" :style="endPointStyle + 'background-color: ' + this.hoopBgColor + ';'" />
    <!-- #ifdef APP-PLUS -->
    <!-- 处理现象: 安卓App的顶部和底部会有一个小白点。 -->
    <!-- <view v-if="ePercent > 0.5" :style="'position: absolute;top: 0;' + repairPointStyle" /> -->
    <!-- <view v-if="1.0 == ePercent" :style="'position: absolute;bottom: 0;' + repairPointStyle" /> -->
    <!-- #endif -->
  </view>
</template>

<!-- 组件名称: 圆环进度条。
     启发地址: https://www.cnblogs.com/jr1993/p/4677921.html 。
     编者信息: 867003077@qq.com 。 -->
<script>
  export default {
    name: 'progressCircle',
    props: {
      // 背景色(不宜设置为透明 否则 需要 在 左thirdLayer 的外面 再嵌套一个盒子)。
      bgColor: {
        type: String,
        default: '#FFFFFF'
      },
      // 圆环的外直径(单位px)。
      diameter: {
        type: Number,
        default: 250
      },
      // 圆环线条的厚度(单位px)。
      hoopThickness: {
        type: Number,
        default: 8
      },
      // 圆环底色(灰色的圆环)。
      hoopBgColor: {
        type: String,
        // default: 'transparent'
        default: '#F3F3F3'
      },
      // 圆环激活部分的颜色。
      hoopColor: {
        type: String,
        default: '#FF4C20'
      },
      // 圆环进度百分比值(其值范围在0到1之间)。
      percent: {
        type: [Number, String],
        default: 0,
        validator: val => {
          return val >= 0 && val <= 1;
        },
      },
      animate: {
        type: Boolean,
        default: false,
      },
    },
    data() {
      return {
        targetPercent: 0,
        ePercent: 0,
        showTimer: undefined,
      };
    },
    watch: {
      percent: {
        handler: function() {
          console.log('progressCircle_watch_percent', this.percent);
          this.loadData();
        },
      },
    },
    computed: {
      firstLayerViewStyle() {
        return 'position: relative;width: ' + (this.diameter / 2) +
          'px;height: ' + this.diameter + 'px;';
      },
      secondLayerViewStyle() {
        return 'box-sizing: border-box;position: absolute;top: 0;width: ' + this.diameter +
          'px;height: ' + this.diameter + 'px;';
      },
      thirdLayerStyle() {
        return 'box-sizing: border-box;width: ' + this.diameter + 'px;height: ' + this.diameter +
          'px;border-radius: ' + (this.diameter / 2) +
          'px;border-width: ' + this.hoopThickness +
          'px;border-style: solid;border-color: ' + this.hoopColor + ';';
      },
      thirdLayerStyleForBg() {
        return 'box-sizing: border-box;position: absolute;top: 0;left: ' + (this.diameter / 2) + 'px;width: ' +
          this.diameter + 'px;height: ' + this.diameter + 'px;background-color: ' + this.bgColor + ';';
      },
      fourthLayerStyleForBg() {
        return 'box-sizing: border-box;margin-left: ' + (-this.diameter / 2) + 'px;width: ' + this.diameter +
          'px;height: ' +
          this.diameter + 'px;border-radius: ' + (this.diameter / 2) + 'px;border-width: ' +
          this.hoopThickness + 'px;border-style: solid;border-color: ' + this.hoopBgColor + ';';
      },
      secondLayerForLeft() {
        let angle = 0;
        if (this.ePercent < 0.5) {
          angle += (180 * (this.ePercent - 0.5) / 0.5);
        }
        // #ifdef APP-PLUS
        return 'left: 0;transform: rotate(' + angle + 'deg);';
        // #endif
        // #ifdef MP-WEIXIN
        return 'left: 0;transform: rotate(' + angle + 'deg);-webkit-transform: rotate(' + angle + 'deg);';
        // #endif
      },
      secondLayerForRight() {
        let angle = 0;
        if (this.ePercent > 0.5) {
          angle += (180 * (this.ePercent - 0.5) / 0.5);
        }
        // #ifdef APP-PLUS
        return 'right: 0;transform: rotate(' + angle + 'deg);';
        // #endif
        // #ifdef MP-WEIXIN
        return 'right: 0;transform: rotate(' + angle + 'deg);-webkit-transform: rotate(' + angle + 'deg);';
        // #endif
      },
      // repairPointStyle() {
      // 	return 'left: ' + (this.diameter - this.hoopThickness) / 2 + 'px;width: ' +
      // 		this.hoopThickness + 'px;height: ' + this.hoopThickness + 'px;border-radius: ' +
      // 		this.hoopThickness / 2 + 'px;background-color: ' + this.hoopColor + ';';
      // },
      endPointStyle() {
        // 结束点圆心圈直径。
        const _circleCenterRadius = 2;
        return 'box-sizing: border-box;position: absolute;top: 0;left: ' + (this.diameter - this.hoopThickness) / 2 +
          'px;width: ' +
          this.hoopThickness + 'px;height: ' + this.hoopThickness + 'px;border-radius: ' + (this.hoopThickness / 2) +
          'px;border-width: ' + (this.hoopThickness / 2 - _circleCenterRadius) +
          'px;border-style: solid;border-color: ' +
          this.hoopColor + ';';
      },
      endPointStyleForLeft() {
        return 'background-color: ' + ((this.ePercent > 0.5) ? this.hoopColor : this.hoopBgColor) + ';';
      },
      endPointStyleForRight() {
        return 'background-color: ' + ((1 == this.ePercent) ? this.hoopColor : this.hoopBgColor) + ';';
      },
    },
    mounted() {
      console.log('progressCircle_mounted');
      this.loadData();
    },
    methods: {
      loadData() {
        this.targetPercent = parseFloat(this.percent);
        console.log('progressCircle_loadData');
        if (!this.animate) {
          this.ePercent = this.targetPercent;
        } else {
          let _this = this;
          this.ePercent = 0;
          this.showTimer && clearInterval(this.showTimer);
          this.showTimer = setInterval(() => {
            let tempPercent = _this.ePercent + 0.1;
            if (tempPercent < _this.targetPercent) {
              _this.ePercent = tempPercent;
              return;
            };
            _this.ePercent = _this.targetPercent;
            clearInterval(_this.showTimer);
          }, 200);
        }
      }
    }
  }
</script>

<style scoped>
  .base-style {
    box-sizing: border-box;
    /* 溢出隐藏 */
    overflow: hidden;
  }
</style>

调用页面:

<template>
  <view class="my-page-container" :style="{ 'height': pageBoxH + 'px' }" @click="currentPercent=0.8">
    <progress-circle class="mine-member-level-progress" :diameter="180" :hoopThickness="10" :hoopColor="'orange'"
      :percent="currentPercent" :animate="true" />
  </view>
</template>

<script>
  /** 演示页面 */
  import progressCircle from "@/components/progress-circle/index.vue";
  // import {
  //   queryDetail,
  // } from '@/api/mine.js';
  export default {
    name: 'myDemo',
    components: {
      progressCircle,
    },
    data() {
      return {
        pageBoxH: 1000,
        currentPercent: 0.25,
      };
    },
    beforeCreate() {
      console.log('beforeCreate enter');
    },
    created() {
      console.log('created enter');
    },
    mounted() {
      console.log('mounted enter');
    },
    onLoad(option) {
      console.log('onLoad enter');
    },
    onReady() {},
    methods: {},
  }
</script>

<style scoped>
  .my-page-container {
    background-color: white;
    box-sizing: border-box;
    padding: 10px 10px 50px 10px;
    display: flex;
    flex-direction: column;
  }
</style>

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

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

相关文章

基于nodejs+vue班级管理系统的设计与实现-flask-django-python-php

随着电子技术的普及和快速发展&#xff0c;线上管理系统被广泛的使用&#xff0c;有很多事业单位和商业机构都在实现电子信息化管理&#xff0c;班级管理系统也不例外&#xff0c;由比较传统的人工管理转向了电子化、信息化、系统化的管理。随着互联网技术的高速发展&#xff0…

基于SpringBoot+Redis实现接口限流

前言 业务中需要对一些接口进行限流处理&#xff0c;防止机器人调用或者保证服务质量&#xff1b; 实现方式 基于redis的lua脚本 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis&…

idea import的maven类报红

idea 报红/显示红色的原因 一般报红&#xff0c;显示红色&#xff0c;是因为 idea 在此路径下&#xff0c;找不到这个类。 找到是哪个 jar 包的类导致 idea 报红 点击报红的路径的上一层&#xff0c;进入jar 包。比如&#xff1a; import com.aaa.bbb.ccc.DddDto;这个 impo…

计算机二级(Python)真题讲解每日一题:《方菱形》

描述‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬ 请写代码替换横线&#xff0…

从服务器到云原生:企业IT基础设施的演进之路

随着数字经济的迅猛发展&#xff0c;企业IT数字化转型已成为推动业务创新和提升竞争力的关键。在这一转型过程中&#xff0c;基础设施的建设与升级显得尤为重要。企业需要不断优化和更新他们的基础设施&#xff0c;以适应不断变化的市场需求和技术发展。本文将探讨企业IT数字化…

大数据面试题 —— Kafka

目录 消息队列 / Kafka 的好处消息队列的两种模式什么是 KafkaKafka 优缺点你在哪些场景下会选择 Kafka讲下 Kafka 的整体结构Kafka 工作原理 / 流程Kafka为什么那么快/高效读写的原因 / 实现高吞吐的原理生产者如何提高吞吐量&#xff08;调优&#xff09;kafka 消息数据积压&…

一维小波包的分解与重构程序深入学习——Matlab

绘制上述图的matlab程序为&#xff1a; clear all; close all; load noisdopp; xnoisdopp; wptwpdec(x,3,db1,shannon) %返回小波包树&#xff0c;设置采用的熵为shannon plot(wpt); %% 学习目标&#xff1a;一维小波包的分解和重构深入学习 %% 获取小波树上某个节点的小…

【滑动窗口、矩阵】算法例题

目录 三、滑动窗口 30. 长度最小的子数组 ② 31. 无重复字符的最长子串 ② 32. 串联所有单词的子串 ③ 33. 最小覆盖子串 ③ 四、矩阵 34. 有效的数独 ② 35. 螺旋矩阵 ② 36. 旋转图像 ② 37. 矩阵置零 ② 38. 生命游戏 ② 三、滑动窗口 30. 长度最小的子数组 ② 给…

Science:量子纠缠突破成像极限

研究专家指出&#xff0c;量子物理学的一些核心特质&#xff0c;如粒子纠缠&#xff0c;为解决一个困扰显微技术领域多年的难题提供了新的思路&#xff1a;如何在极小的尺度上获得更清晰的图像。 这项创新性的研究通过利用纠缠光子&#xff0c;开发出了一种新技术&#xff0c;能…

Web前端-HTML

HTML 负责页面的结构&#xff08;页面的元素和内容&#xff09; HTML由标签组成&#xff0c;标签都是预定义好的。例如<a>展示超链接&#xff0c;使用<img>展示图片&#xff0c;<vedio>展示视频。 HTML代码直接在浏览器中运行&#xff0c;HTML标签由浏览器…

在微信小程序中或UniApp中自定义tabbar实现毛玻璃高斯模糊效果

backdrop-filter: blur(10px); 这一行代码表示将背景进行模糊处理&#xff0c;模糊程度为10像素。这会导致背景内容在这个元素后面呈现模糊效果。 background-color: rgb(255 255 255 / .32); 这一行代码表示设置元素的背景颜色为白色&#xff08;RGB值为0, 0, 0&#xff09;&a…

行业模板|DataEase制造行业大屏模板推荐

DataEase开源数据可视化分析平台于2022年6月发布模板市场&#xff08;https://templates-de.fit2cloud.com&#xff09;&#xff0c;并于2024年1月新增适用于DataEase v2版本的模板分类。模板市场旨在为DataEase用户提供专业、美观、拿来即用的大屏模板&#xff0c;方便用户根据…

Stable Diffusion WebUI 生成参数:高清修复/高分辨率修复(Hires.fix)

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 大家好&#xff0c;我是水滴~~ 在本篇文章中&#xff0c;我们将深入探讨 Stable Diffusion WebUI 的一个引人注目的生成参数——高分辨率修复&#xff08;Hires.fix&#xff09;。我们将逐一…

添加与搜索单词 - 数据结构设计

题目链接 添加与搜索单词 - 数据结构设计 题目描述 注意点 addWord 中的 word 由小写英文字母组成search 中的 word 由 ‘.’ 或小写英文字母组成1 < word.length < 25 解答思路 为了加快查询速度&#xff0c;可以使用字典树存储单词&#xff0c;基本结构是&#xf…

Linux: network: firewall: firewalld 导致icmp带admin prohibited

文章目录 简介查看相关的配置产生的rule不在rule里的被拒绝重新加载iptables服务进程简介 https://firewalld.org/documentation/man-pages/firewalld.zone.html 最近遇到一个主机主动回icmp,destination unreachable的错误包,而且里面的code是 administratively prohibited…

Flutter与Xamarin跨平台APP开发框架的区别

嘿&#xff0c;各位亲爱的朋友们&#xff01;大家好&#xff0c;我是咕噜铁蛋&#xff01;今天我们要探讨的话题是&#xff1a;Flutter与Xamarin这两款热门的跨平台APP开发框架。我深知选择合适的开发工具对于开发者来说有多么重要。那么&#xff0c;当我们需要开发跨平台应用时…

[Qt项目实战]Qt实现美松标签打印机标签二维码打印(QR混排模式+页打印模式)

1、硬件信息、环境参数及配套资料 1.1 打印机信息及开发环境 打印机 美松标签打印机串口/USB通讯Qt5.9 64位程序 1.2 打印机配套开发资料 打印机主要配套测试工具、开发SDK及驱动等&#xff0c;均由厂家提供。 开发Demo及动态库&#xff1a;MsPrintSDK-DLL-V2.2.2.5 链接&…

只需3步,使用Stable Diffusion无限生成AI数字人视频

基本方法 搞一张照片&#xff0c;搞一段语音&#xff0c;合成照片和语音&#xff0c;同时让照片中的人物动起来&#xff0c;特别是头、眼睛和嘴。 语音合成 语音合成的方法很多&#xff0c;也比较成熟了&#xff0c;大家可以选择自己方便的&#xff0c;直接录音也可以&#…

Linux TCP参数——tcp_allowed_congestion_control

tcp_allowed_congestion_control 设置允许普通进程使用的拥塞控制算法。这个参数的值阈是tcp_available_congestion_control参数的子集。默认值为"reno"加上tcp_congestion_control参数设置的算法。 reno 慢启动阶段&#xff1a;在开始的时候&#xff0c;cwnd按指数…

创建自己的“百度网盘”(部署owncloud)

[rootlocalhost html]# cd /root/[rootlocalhost ~]# wget https://download.com/server/stable/owncloud-10.12.0.zip --no-check-certificate #下载当前的owncloud代码包[rootlocalhost ~]# yum -y install unzip #安装解压工具[rootlocalhost ~]# unzip owncloud-10.12.0.zi…